题目描述
给你 3 个正整数 zero
,one
和 limit
。
一个 二进制数组 arr
如果满足以下条件,那么我们称它是 稳定的 :
- 0 在
arr
中出现次数 恰好 为 zero
。
- 1 在
arr
中出现次数 恰好 为 one
。
arr
中每个长度超过 limit
的 子数组 都 同时 包含 0 和 1 。
请你返回 稳定 二进制数组的 总 数目。
由于答案可能很大,将它对 109 + 7
取余 后返回。
示例 1:
输入:zero = 1, one = 1, limit = 2
输出:2
解释:
两个稳定的二进制数组为 [1,0]
和 [0,1]
,两个数组都有一个 0 和一个 1 ,且没有子数组长度大于 2 。
示例 2:
输入:zero = 1, one = 2, limit = 1
输出:1
解释:
唯一稳定的二进制数组是 [1,0,1]
。
二进制数组 [1,1,0]
和 [0,1,1]
都有长度为 2 且元素全都相同的子数组,所以它们不稳定。
示例 3:
输入:zero = 3, one = 3, limit = 2
输出:14
解释:
所有稳定的二进制数组包括 [0,0,1,0,1,1]
,[0,0,1,1,0,1]
,[0,1,0,0,1,1]
,[0,1,0,1,0,1]
,[0,1,0,1,1,0]
,[0,1,1,0,0,1]
,[0,1,1,0,1,0]
,[1,0,0,1,0,1]
,[1,0,0,1,1,0]
,[1,0,1,0,0,1]
,[1,0,1,0,1,0]
,[1,0,1,1,0,0]
,[1,1,0,0,1,0]
和 [1,1,0,1,0,0]
。
提示:
1 <= zero, one, limit <= 200
解法
方法一:记忆化搜索
我们设计一个函数 $dfs(i, j, k)$ 表示还剩下 $i$ 个 $0$ 和 $j$ 个 $1$ 且接下来待填的数字是 $k$ 的情况下,满足题目条件的稳定二进制数组的个数。那么答案就是 $dfs(zero, one, 0) + dfs(zero, one, 1)$。
函数 $dfs(i, j, k)$ 的计算过程如下:
- 如果 $i \lt 0$ 或 $j \lt 0$,返回 $0$。
- 如果 $i = 0$,那么当 $k = 1$ 且 $j \leq \textit{limit}$ 时返回 $1$,否则返回 $0$。
- 如果 $j = 0$,那么当 $k = 0$ 且 $i \leq \textit{limit}$ 时返回 $1$,否则返回 $0$。
- 如果 $k = 0$,我们考虑前一个数字是 $0$ 的情况 $dfs(i - 1, j, 0)$ 和前一个数字是 $1$ 的情况 $dfs(i - 1, j, 1)$,如果前一个数是 $0$,那么有可能使得子数组中有超过 $\textit{limit}$ 个 $0$,即不允许出现倒数第 $\textit{limit} + 1$ 个数是 $1$ 的情况,所以我们要减去这种情况,即 $dfs(i - \textit{limit} - 1, j, 1)$。
- 如果 $k = 1$,我们考虑前一个数字是 $0$ 的情况 $dfs(i, j - 1, 0)$ 和前一个数字是 $1$ 的情况 $dfs(i, j - 1, 1)$,如果前一个数是 $1$,那么有可能使得子数组中有超过 $\textit{limit}$ 个 $1$,即不允许出现倒数第 $\textit{limit} + 1$ 个数是 $0$ 的情况,所以我们要减去这种情况,即 $dfs(i, j - \textit{limit} - 1, 0)$。
为了避免重复计算,我们使用记忆化搜索的方法。
时间复杂度 $O(zero \times one)$,空间复杂度 $O(zero \times one)$。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | class Solution:
def numberOfStableArrays(self, zero: int, one: int, limit: int) -> int:
@cache
def dfs(i: int, j: int, k: int) -> int:
if i == 0:
return int(k == 1 and j <= limit)
if j == 0:
return int(k == 0 and i <= limit)
if k == 0:
return (
dfs(i - 1, j, 0)
+ dfs(i - 1, j, 1)
- (0 if i - limit - 1 < 0 else dfs(i - limit - 1, j, 1))
)
return (
dfs(i, j - 1, 0)
+ dfs(i, j - 1, 1)
- (0 if j - limit - 1 < 0 else dfs(i, j - limit - 1, 0))
)
mod = 10**9 + 7
ans = (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod
dfs.cache_clear()
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 | class Solution {
private final int mod = (int) 1e9 + 7;
private Long[][][] f;
private int limit;
public int numberOfStableArrays(int zero, int one, int limit) {
f = new Long[zero + 1][one + 1][2];
this.limit = limit;
return (int) ((dfs(zero, one, 0) + dfs(zero, one, 1)) % mod);
}
private long dfs(int i, int j, int k) {
if (i < 0 || j < 0) {
return 0;
}
if (i == 0) {
return k == 1 && j <= limit ? 1 : 0;
}
if (j == 0) {
return k == 0 && i <= limit ? 1 : 0;
}
if (f[i][j][k] != null) {
return f[i][j][k];
}
if (k == 0) {
f[i][j][k]
= (dfs(i - 1, j, 0) + dfs(i - 1, j, 1) - dfs(i - limit - 1, j, 1) + mod) % mod;
} else {
f[i][j][k]
= (dfs(i, j - 1, 0) + dfs(i, j - 1, 1) - dfs(i, j - limit - 1, 0) + mod) % mod;
}
return f[i][j][k];
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 | class Solution {
public:
int numberOfStableArrays(int zero, int one, int limit) {
const int mod = 1e9 + 7;
using ll = long long;
vector<vector<array<ll, 2>>> f = vector<vector<array<ll, 2>>>(zero + 1, vector<array<ll, 2>>(one + 1, {-1, -1}));
auto dfs = [&](auto&& dfs, int i, int j, int k) -> ll {
if (i < 0 || j < 0) {
return 0;
}
if (i == 0) {
return k == 1 && j <= limit;
}
if (j == 0) {
return k == 0 && i <= limit;
}
ll& res = f[i][j][k];
if (res != -1) {
return res;
}
if (k == 0) {
res = (dfs(dfs, i - 1, j, 0) + dfs(dfs, i - 1, j, 1) - dfs(dfs, i - limit - 1, j, 1) + mod) % mod;
} else {
res = (dfs(dfs, i, j - 1, 0) + dfs(dfs, i, j - 1, 1) - dfs(dfs, i, j - limit - 1, 0) + mod) % mod;
}
return res;
};
return (dfs(dfs, zero, one, 0) + dfs(dfs, zero, one, 1)) % mod;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 | func numberOfStableArrays(zero int, one int, limit int) int {
const mod int = 1e9 + 7
f := make([][][2]int, zero+1)
for i := range f {
f[i] = make([][2]int, one+1)
for j := range f[i] {
f[i][j] = [2]int{-1, -1}
}
}
var dfs func(i, j, k int) int
dfs = func(i, j, k int) int {
if i < 0 || j < 0 {
return 0
}
if i == 0 {
if k == 1 && j <= limit {
return 1
}
return 0
}
if j == 0 {
if k == 0 && i <= limit {
return 1
}
return 0
}
res := &f[i][j][k]
if *res != -1 {
return *res
}
if k == 0 {
*res = (dfs(i-1, j, 0) + dfs(i-1, j, 1) - dfs(i-limit-1, j, 1) + mod) % mod
} else {
*res = (dfs(i, j-1, 0) + dfs(i, j-1, 1) - dfs(i, j-limit-1, 0) + mod) % mod
}
return *res
}
return (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 | function numberOfStableArrays(zero: number, one: number, limit: number): number {
const mod = 1e9 + 7;
const f: number[][][] = Array.from({ length: zero + 1 }, () =>
Array.from({ length: one + 1 }, () => [-1, -1]),
);
const dfs = (i: number, j: number, k: number): number => {
if (i < 0 || j < 0) {
return 0;
}
if (i === 0) {
return k === 1 && j <= limit ? 1 : 0;
}
if (j === 0) {
return k === 0 && i <= limit ? 1 : 0;
}
let res = f[i][j][k];
if (res !== -1) {
return res;
}
if (k === 0) {
res = (dfs(i - 1, j, 0) + dfs(i - 1, j, 1) - dfs(i - limit - 1, j, 1) + mod) % mod;
} else {
res = (dfs(i, j - 1, 0) + dfs(i, j - 1, 1) - dfs(i, j - limit - 1, 0) + mod) % mod;
}
return (f[i][j][k] = res);
};
return (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod;
}
|
方法二:动态规划
我们也可以将方法一的记忆化搜索转换为动态规划。
我们定义 $f[i][j][k]$ 表示使用 $i$ 个 $0$ 和 $j$ 个 $1$ 且最后一个数字是 $k$ 的稳定二进制数组的个数。那么答案就是 $f[zero][one][0] + f[zero][one][1]$。
初始时,我们有 $f[i][0][0] = 1$,其中 $1 \leq i \leq \min(\textit{limit}, \textit{zero})$;有 $f[0][j][1] = 1$,其中 $1 \leq j \leq \min(\textit{limit}, \textit{one})$。
状态转移方程如下:
- $f[i][j][0] = f[i - 1][j][0] + f[i - 1][j][1] - f[i - \textit{limit} - 1][j][1]$。
- $f[i][j][1] = f[i][j - 1][0] + f[i][j - 1][1] - f[i][j - \textit{limit} - 1][0]$。
时间复杂度 $O(zero \times one)$,空间复杂度 $O(zero \times one)$。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | class Solution:
def numberOfStableArrays(self, zero: int, one: int, limit: int) -> int:
mod = 10**9 + 7
f = [[[0, 0] for _ in range(one + 1)] for _ in range(zero + 1)]
for i in range(1, min(limit, zero) + 1):
f[i][0][0] = 1
for j in range(1, min(limit, one) + 1):
f[0][j][1] = 1
for i in range(1, zero + 1):
for j in range(1, one + 1):
x = 0 if i - limit - 1 < 0 else f[i - limit - 1][j][1]
y = 0 if j - limit - 1 < 0 else f[i][j - limit - 1][0]
f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x) % mod
f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y) % mod
return sum(f[zero][one]) % mod
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | class Solution {
public int numberOfStableArrays(int zero, int one, int limit) {
final int mod = (int) 1e9 + 7;
long[][][] f = new long[zero + 1][one + 1][2];
for (int i = 1; i <= Math.min(zero, limit); ++i) {
f[i][0][0] = 1;
}
for (int j = 1; j <= Math.min(one, limit); ++j) {
f[0][j][1] = 1;
}
for (int i = 1; i <= zero; ++i) {
for (int j = 1; j <= one; ++j) {
long x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1];
long y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0];
f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod;
f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod;
}
}
return (int) ((f[zero][one][0] + f[zero][one][1]) % mod);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | class Solution {
public:
int numberOfStableArrays(int zero, int one, int limit) {
const int mod = 1e9 + 7;
using ll = long long;
ll f[zero + 1][one + 1][2];
memset(f, 0, sizeof(f));
for (int i = 1; i <= min(zero, limit); ++i) {
f[i][0][0] = 1;
}
for (int j = 1; j <= min(one, limit); ++j) {
f[0][j][1] = 1;
}
for (int i = 1; i <= zero; ++i) {
for (int j = 1; j <= one; ++j) {
ll x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1];
ll y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0];
f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod;
f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod;
}
}
return (f[zero][one][0] + f[zero][one][1]) % mod;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | func numberOfStableArrays(zero int, one int, limit int) int {
const mod int = 1e9 + 7
f := make([][][2]int, zero+1)
for i := range f {
f[i] = make([][2]int, one+1)
}
for i := 1; i <= min(zero, limit); i++ {
f[i][0][0] = 1
}
for j := 1; j <= min(one, limit); j++ {
f[0][j][1] = 1
}
for i := 1; i <= zero; i++ {
for j := 1; j <= one; j++ {
f[i][j][0] = (f[i-1][j][0] + f[i-1][j][1]) % mod
if i-limit-1 >= 0 {
f[i][j][0] = (f[i][j][0] - f[i-limit-1][j][1] + mod) % mod
}
f[i][j][1] = (f[i][j-1][0] + f[i][j-1][1]) % mod
if j-limit-1 >= 0 {
f[i][j][1] = (f[i][j][1] - f[i][j-limit-1][0] + mod) % mod
}
}
}
return (f[zero][one][0] + f[zero][one][1]) % mod
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | function numberOfStableArrays(zero: number, one: number, limit: number): number {
const mod = 1e9 + 7;
const f: number[][][] = Array.from({ length: zero + 1 }, () =>
Array.from({ length: one + 1 }, () => [0, 0]),
);
for (let i = 1; i <= Math.min(limit, zero); i++) {
f[i][0][0] = 1;
}
for (let j = 1; j <= Math.min(limit, one); j++) {
f[0][j][1] = 1;
}
for (let i = 1; i <= zero; i++) {
for (let j = 1; j <= one; j++) {
const x = i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1];
const y = j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0];
f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1] - x + mod) % mod;
f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1] - y + mod) % mod;
}
}
return (f[zero][one][0] + f[zero][one][1]) % mod;
}
|