Skip to content

Files

Latest commit

c29b144 · May 17, 2024

History

History
This branch is 2 commits ahead of, 1229 commits behind doocs/leetcode:main.

3130.Find All Possible Stable Binary Arrays II

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
May 17, 2024
May 17, 2024
Apr 29, 2024
Apr 29, 2024
Apr 29, 2024
Apr 29, 2024
Apr 29, 2024
Apr 29, 2024
Apr 29, 2024
Apr 29, 2024
comments difficulty edit_url rating source tags
true
困难
2824
第 129 场双周赛 Q4
动态规划
前缀和

English Version

题目描述

给你 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 <= 1000

解法

方法一:记忆化搜索

我们设计一个函数 d f s ( i , j , k ) 表示还剩下 i 0 j 1 且接下来待填的数字是 k 的情况下,满足题目条件的稳定二进制数组的个数。那么答案就是 d f s ( z e r o , o n e , 0 ) + d f s ( z e r o , o n e , 1 )

函数 d f s ( i , j , k ) 的计算过程如下:

  • 如果 i < 0 j < 0 ,返回 0
  • 如果 i = 0 ,那么当 k = 1 j limit 时返回 1 ,否则返回 0
  • 如果 j = 0 ,那么当 k = 0 i limit 时返回 1 ,否则返回 0
  • 如果 k = 0 ,我们考虑前一个数字是 0 的情况 d f s ( i 1 , j , 0 ) 和前一个数字是 1 的情况 d f s ( i 1 , j , 1 ) ,如果前一个数是 0 ,那么有可能使得子数组中有超过 limit 0 ,即不允许出现倒数第 limit + 1 个数是 1 的情况,所以我们要减去这种情况,即 d f s ( i limit 1 , j , 1 )
  • 如果 k = 1 ,我们考虑前一个数字是 0 的情况 d f s ( i , j 1 , 0 ) 和前一个数字是 1 的情况 d f s ( i , j 1 , 1 ) ,如果前一个数是 1 ,那么有可能使得子数组中有超过 limit 1 ,即不允许出现倒数第 limit + 1 个数是 0 的情况,所以我们要减去这种情况,即 d f s ( i , j limit 1 , 0 )

为了避免重复计算,我们使用记忆化搜索的方法。

时间复杂度 O ( z e r o × o n e ) ,空间复杂度 O ( z e r o × o n e )

Python3

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

Java

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];
    }
}

C++

using ll = long long;

class Solution {
public:
    int numberOfStableArrays(int zero, int one, int limit) {
        this->limit = limit;
        f = vector<vector<array<ll, 2>>>(zero + 1, vector<array<ll, 2>>(one + 1, {-1, -1}));
        return (dfs(zero, one, 0) + dfs(zero, one, 1)) % mod;
    }

private:
    const int mod = 1e9 + 7;
    int limit;
    vector<vector<array<ll, 2>>> f;

    ll dfs(int i, int j, int k) {
        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(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;
    }
};

Go

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
}

方法二:动态规划

我们也可以将方法一的记忆化搜索转换为动态规划。

我们定义 f [ i ] [ j ] [ k ] 表示使用 i 0 j 1 且最后一个数字是 k 的稳定二进制数组的个数。那么答案就是 f [ z e r o ] [ o n e ] [ 0 ] + f [ z e r o ] [ o n e ] [ 1 ]

初始时,我们有 f [ i ] [ 0 ] [ 0 ] = 1 ,其中 1 i min ( limit , zero ) ;有 f [ 0 ] [ j ] [ 1 ] = 1 ,其中 1 j min ( limit , one )

状态转移方程如下:

  • f [ i ] [ j ] [ 0 ] = f [ i 1 ] [ j ] [ 0 ] + f [ i 1 ] [ j ] [ 1 ] f [ i limit 1 ] [ j ] [ 1 ]
  • f [ i ] [ j ] [ 1 ] = f [ i ] [ j 1 ] [ 0 ] + f [ i ] [ j 1 ] [ 1 ] f [ i ] [ j limit 1 ] [ 0 ]

时间复杂度 O ( z e r o × o n e ) ,空间复杂度 O ( z e r o × o n e )

Python3

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):
                f[i][j][0] = (
                    f[i - 1][j][0]
                    + f[i - 1][j][1]
                    - (0 if i - limit - 1 < 0 else f[i - limit - 1][j][1])
                ) % mod
                f[i][j][1] = (
                    f[i][j - 1][0]
                    + f[i][j - 1][1]
                    - (0 if j - limit - 1 < 0 else f[i][j - limit - 1][0])
                ) % mod
        return sum(f[zero][one]) % mod

Java

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) {
                f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1]
                                 - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod)
                    % mod;
                f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1]
                                 - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod)
                    % mod;
            }
        }
        return (int) ((f[zero][one][0] + f[zero][one][1]) % mod);
    }
}

C++

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) {
                f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1]
                                 - (i - limit - 1 < 0 ? 0 : f[i - limit - 1][j][1]) + mod)
                    % mod;
                f[i][j][1] = (f[i][j - 1][0] + f[i][j - 1][1]
                                 - (j - limit - 1 < 0 ? 0 : f[i][j - limit - 1][0]) + mod)
                    % mod;
            }
        }
        return (f[zero][one][0] + f[zero][one][1]) % mod;
    }
};

Go

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
}