-
Problem Summary
-
Constraints
-
Intuition
-
Approach
-
Data Structures Used
-
Operations & Behavior Summary
-
Complexity
-
Multi-language Solutions
- C++
- Java
- JavaScript
- Python3
- Go
-
Step-by-step Detailed Explanation
-
Examples
-
How to use / Run locally
-
Notes & Optimizations
-
Author
We are given three integers:
zero→ number of 0sone→ number of 1slimit→ maximum number of consecutive equal values allowed
A binary array is called stable if:
- It contains exactly
zeronumber of0s - It contains exactly
onenumber of1s - No subarray longer than
limitcontains only0s or only1s
In simple terms:
- We cannot have more than
limitconsecutive0s - We cannot have more than
limitconsecutive1s
Our goal is to count how many such valid arrays exist.
Because the answer can be very large, we return the result modulo 1e9 + 7.
1 <= zero, one, limit <= 1000
The solution must therefore be efficient enough to handle up to 1000 × 1000 states.
When I first read the problem, I noticed that the main restriction is about consecutive numbers.
So I started thinking about building the binary array step by step.
At each step I can place either:
01
But I must make sure I never create more than limit identical consecutive values.
This naturally suggests a Dynamic Programming solution.
I decided to track:
- how many zeros I used
- how many ones I used
- what the last placed value was
This allows me to enforce the consecutive limit rule.
Let:
dp[i][j][0] = number of arrays using i zeros and j ones ending with 0
dp[i][j][1] = number of arrays using i zeros and j ones ending with 1
Where:
i= zeros usedj= ones used
If the array contains only zeros:
dp[i][0][0] = 1 if i <= limit
Similarly for ones:
dp[0][j][1] = 1 if j <= limit
Because longer sequences would violate the limit.
If we want to end with 0:
We append 0 to a previous array.
dp[i][j][0] = dp[i-1][j][0] + dp[i-1][j][1]
However, we must subtract cases where we exceed the limit consecutive 0s.
Those cases occur when the sequence started with 1 and then added limit+1 zeros.
So we subtract:
dp[i-limit-1][j][1]
Similarly for 1:
dp[i][j][1] = dp[i][j-1][0] + dp[i][j-1][1]
And subtract invalid sequences:
dp[i][j-limit-1][0]
The array may end with either value:
answer = dp[zero][one][0] + dp[zero][one][1]
The solution uses a 3D Dynamic Programming array:
dp[zero+1][one+1][2]
The third dimension represents the last element:
0→ array ends with zero1→ array ends with one
| Operation | Purpose |
|---|---|
| Initialize base states | Valid sequences of only zeros or only ones |
| DP transitions | Extend previous sequences |
| Subtract invalid states | Prevent exceeding consecutive limit |
| Modulo operation | Prevent integer overflow |
O(zero × one)
We compute each DP state once.
O(zero × one)
For storing the DP table.
class Solution {
public:
int numberOfStableArrays(int zero, int one, int limit) {
const int MOD = 1e9 + 7;
vector<vector<array<long long,2>>> dp(
zero+1, vector<array<long long,2>>(one+1,{0,0}));
for(int i=1;i<=min(zero,limit);i++)
dp[i][0][0]=1;
for(int j=1;j<=min(one,limit);j++)
dp[0][j][1]=1;
for(int i=1;i<=zero;i++){
for(int j=1;j<=one;j++){
long long over0=(i-limit-1>=0)?dp[i-limit-1][j][1]:0;
long long over1=(j-limit-1>=0)?dp[i][j-limit-1][0]:0;
dp[i][j][0]=(dp[i-1][j][0]+dp[i-1][j][1]-over0+MOD)%MOD;
dp[i][j][1]=(dp[i][j-1][0]+dp[i][j-1][1]-over1+MOD)%MOD;
}
}
return (dp[zero][one][0]+dp[zero][one][1])%MOD;
}
};class Solution {
public int numberOfStableArrays(int zero, int one, int limit) {
int MOD = 1_000_000_007;
long[][][] dp = new long[zero+1][one+1][2];
for(int i=1;i<=Math.min(zero,limit);i++)
dp[i][0][0]=1;
for(int j=1;j<=Math.min(one,limit);j++)
dp[0][j][1]=1;
for(int i=1;i<=zero;i++){
for(int j=1;j<=one;j++){
long over0=(i-limit-1>=0)?dp[i-limit-1][j][1]:0;
long over1=(j-limit-1>=0)?dp[i][j-limit-1][0]:0;
dp[i][j][0]=(dp[i-1][j][0]+dp[i-1][j][1]-over0+MOD)%MOD;
dp[i][j][1]=(dp[i][j-1][0]+dp[i][j-1][1]-over1+MOD)%MOD;
}
}
return (int)((dp[zero][one][0]+dp[zero][one][1])%MOD);
}
}var numberOfStableArrays = function(zero, one, limit) {
const MOD = 1000000007;
const dp = Array.from({length: zero+1},()=>
Array.from({length: one+1},()=>[0,0])
);
for(let i=1;i<=Math.min(zero,limit);i++)
dp[i][0][0]=1;
for(let j=1;j<=Math.min(one,limit);j++)
dp[0][j][1]=1;
for(let i=1;i<=zero;i++){
for(let j=1;j<=one;j++){
let over0=(i-limit-1>=0)?dp[i-limit-1][j][1]:0;
let over1=(j-limit-1>=0)?dp[i][j-limit-1][0]:0;
dp[i][j][0]=(dp[i-1][j][0]+dp[i-1][j][1]-over0+MOD)%MOD;
dp[i][j][1]=(dp[i][j-1][0]+dp[i][j-1][1]-over1+MOD)%MOD;
}
}
return (dp[zero][one][0]+dp[zero][one][1])%MOD;
};class Solution:
def numberOfStableArrays(self, zero: int, one: int, limit: int) -> int:
MOD = 10**9 + 7
dp = [[[0,0] for _ in range(one+1)] for _ in range(zero+1)]
for i in range(1,min(zero,limit)+1):
dp[i][0][0]=1
for j in range(1,min(one,limit)+1):
dp[0][j][1]=1
for i in range(1,zero+1):
for j in range(1,one+1):
over0 = dp[i-limit-1][j][1] if i-limit-1>=0 else 0
over1 = dp[i][j-limit-1][0] if j-limit-1>=0 else 0
dp[i][j][0]=(dp[i-1][j][0]+dp[i-1][j][1]-over0)%MOD
dp[i][j][1]=(dp[i][j-1][0]+dp[i][j-1][1]-over1)%MOD
return (dp[zero][one][0]+dp[zero][one][1])%MODfunc numberOfStableArrays(zero int, one int, limit int) int {
const MOD int = 1e9 + 7
dp := make([][][]int, zero+1)
for i:=range dp{
dp[i]=make([][]int,one+1)
for j:=range dp[i]{
dp[i][j]=make([]int,2)
}
}
for i:=1;i<=min(zero,limit);i++{
dp[i][0][0]=1
}
for j:=1;j<=min(one,limit);j++{
dp[0][j][1]=1
}
for i:=1;i<=zero;i++{
for j:=1;j<=one;j++{
over0:=0
if i-limit-1>=0{
over0=dp[i-limit-1][j][1]
}
over1:=0
if j-limit-1>=0{
over1=dp[i][j-limit-1][0]
}
dp[i][j][0]=(dp[i-1][j][0]+dp[i-1][j][1]-over0+MOD)%MOD
dp[i][j][1]=(dp[i][j-1][0]+dp[i][j-1][1]-over1+MOD)%MOD
}
}
return (dp[zero][one][0]+dp[zero][one][1])%MOD
}
func min(a,b int) int{
if a<b{return a}
return b
}-
Create a DP table that tracks zeros used, ones used, and last element.
-
Initialize base states for sequences containing only zeros or only ones.
-
Iterate through all
(i, j)states. -
For each state:
- Extend sequences ending with zero
- Extend sequences ending with one
-
Subtract invalid sequences that exceed the
limitconsecutive rule. -
Apply modulo to prevent overflow.
-
Return the sum of sequences ending with
0and1.
Input
zero = 1
one = 1
limit = 2
Output
2
Valid arrays
[1,0]
[0,1]
Input
zero = 1
one = 2
limit = 1
Output
1
Valid array
[1,0,1]
Example for C++:
g++ solution.cpp -o solution
./solution
Example for Python:
python solution.py
- Dynamic Programming avoids exponential recursion.
- Subtracting invalid sequences ensures the limit constraint is satisfied.
- Using modulo prevents integer overflow.
Possible improvement:
- Space optimization could reduce memory usage.