Count Ways To Build Good Strings
Problem
Given the integers zero, one, low, and high, we can construct a string by starting with an empty string, and then at each step perform either of the following:
- Append the character
'0'zerotimes. - Append the character
'1'onetimes.
This can be performed any number of times.
A good string is a string constructed by the above process having a length between low and high (inclusive).
Return the number of different good strings that can be constructed satisfying these properties. Since the answer can be large, return it modulo 10^9 + 7.
Examples
Example 1:
Input: low = 3, high = 3, zero = 1, one = 1
Output: 8
Explanation:
One possible valid good string is "011".
It can be constructed as follows: "" -> "0" -> "01" -> "011".
All binary strings from "000" to "111" are good strings in this example.
Example 2:
Input: low = 2, high = 3, zero = 1, one = 2
Output: 5
Explanation: The good strings are "00", "11", "000", "110", and "011".
Solution
Method 1 - Using Dynamic Programming
To solve this problem, we can use dynamic programming (DP). We'll define a DP array dp where dp[i] represents the number of ways to construct a good string of length i.
For each length i from low to high, we can build on previous results:
- If we append
'0'zerotimes to a string of lengthi-zero, it'll form a good string of lengthi. - If we append
'1'onetimes to a string of lengthi-one, it'll form a good string of lengthi.
We'll sum up all the dp values from low to high to get our final answer.
Approach
- Define DP Array:
- Initialize a DP array
dpof sizehigh + 1with all zeros, exceptdp[0]which is 1 because there's one way to construct a string of length 0 (the empty string).
- Initialize a DP array
- Fill DP Array:
- Iterate over each
lengthfrom 1 tohigh. - For each length, add the counts where:
length >= zerofromdp[length - zero].length >= onefromdp[length - one].
- Iterate over each
- Result Calculation:
- Sum up all values in
dpfromlowtohigh.
- Sum up all values in
- Modulo Operation:
- Apply modulo
10^9 + 7at each step to ensure the result fits within limits.
- Apply modulo
Code
Java
class Solution {
public int countGoodStrings(int zero, int one, int low, int high) {
final int MOD = 1_000_000_007;
int[] dp = new int[high + 1];
dp[0] = 1; // Base case: one way to construct a string of length 0
for (int length = 1; length <= high; length++) {
if (length >= zero) {
dp[length] += dp[length - zero];
}
if (length >= one) {
dp[length] += dp[length - one];
}
dp[length] %= MOD;
}
// Sum the number of good strings from length low to high
int ans = 0;
for (int length = low; length <= high; length++) {
ans = (ans + dp[length]) % MOD;
}
return ans;
}
}
Python
class Solution:
def countGoodStrings(self, zero: int, one: int, low: int, high: int) -> int:
MOD = 10**9 + 7
dp = [0] * (high + 1)
dp[0] = 1 # Base case: one way to construct a string of length 0
for length in range(1, high + 1):
if length >= zero:
dp[length] += dp[length - zero]
if length >= one:
dp[length] += dp[length - one]
dp[length] %= MOD
# Sum the number of good strings from length low to high
ans = sum(dp[low:high + 1]) % MOD
return ans
Complexity
- ⏰ Time complexity:
O(high), wherehighis the upper bound of the string length. We process each length up tohigh. - 🧺 Space complexity:
O(high), due to the storage required for the DP array.