Problem Description
Given a string s, partition it into one or more substrings such that each substring is balanced. A balanced substring is defined as one in which every character present appears the same number of times. For example, while "aabb" is balanced (each character appears twice), "aabbc" is not balanced. The goal is to determine the minimum number of balanced substrings the string can be split into.
Key Insights
- Every single character is balanced on its own.
- A substring is balanced if all its nonzero character frequencies are equal.
- We can use a dynamic programming approach where dp[i] represents the minimum number of balanced substrings for the prefix ending at index i-1.
- We can incrementally build candidate substrings by expanding the window and checking if the substring remains balanced (using a fixed character frequency array of size 26).
- The overall time complexity is acceptable since checking balance for a candidate substring takes constant time (O(26)).
Space and Time Complexity
Time Complexity: O(n^2)
Space Complexity: O(n) (for the dp array, with constant space for frequency arrays)
Solution
We solve the problem using dynamic programming. First, we initialize a dp array where dp[i] is the minimum number of balanced substrings for s[0:i]. We then iterate over every possible starting index i. For each i, we use an inner loop to expand the candidate substring s[i:j+1] while maintaining a frequency count for the 26 lowercase letters. At every step, we check if the nonzero frequencies in the current substring are all equal. If they are, we update dp[j+1] to be the minimum of itself and dp[i] + 1. In the end, dp[n] will hold the minimum number of balanced substrings for the entire string.
The trick lies in efficiently checking substring balance by updating the frequency count in the inner loop and checking all 26 positions, which is a constant operation.