2024/08/06 每日一题

LeetCode 3129 找出所有稳定的二进制数组I

方法1:动态规划

第一步:定义 DP 数组

dp0[i][j]:填入 i0j1,并且最后填 0 的方案数
dp1[i][j]:填入 i0j1,并且最后填 1 的方案数

第二步:状态转移方程

(1)dp0[i][j] 表示第 i+j 位置将填入 0,故 i+j1 位可能填了 01

  • i+j1 位填了 1,从 dp1[i1][j] 转移,由于其尾部填 1,故可以直接转移
  • i+j1 位填了 0,从dp0[i1][j] 转移,但需要判别 i+j0 是否合法
    • 如果 ilimit,则 i+j 填入 0 对所有方案 dp0[i1][j] 均是合法的
    • 如果 i>limit,则 i+j 填入 0 对所有方案 dp0[i1][j] 中的部分方案是不合法的
      • i+j 填入 0 不合法,即从此方案 dp1[ilimit1][j] 开始已经填入了 limit0

(2)dp1[i][j] 表示第 i+j 位置将填入 1,故 i+j1 位可能填了 01

  • i+j1 位填了 0,从 dp0[i][j1] 转移,由于其尾部填 0,故可以直接转移
  • i+j1 位填了 1,从dp1[i][j1] 转移,但需要判别 i+j1 是否合法
    • 如果 ilimit,则 i+j 填入 1 对所有方案 dp1[i][j1] 均是合法的
    • 如果 i>limit,则 i+j 填入 1 对所有方案 dp1[i][j1] 中的部分方案是不合法的
      • i+j 填入 1 不合法,即从此方案 dp0[i][jlimit1] 开始已经填入了 limit1

第三步:初始化 DP 数组

(1)从第二步可知,dp0[i][j] 需要知道 dp0[i1][j]dp1[i1][j],故需要初始化第一行和第一列

  • 如果 i=0;j=0,则 dp0[0][0]=1
  • 如果 i=0;j=1one0 的个数是 0,故 dp0[0][j]=0
  • 如果 i=1zero;j=01 的个数是 0,但只能连续填 limit0,故 dp0[0min(zero,limit)][0]=1,其余为 0

(2)从第二步可知,dp1[i][j] 需要知道 dp0[i][j1]dp1[i][j1],故需要初始化第一行和第一列

  • 如果 i=0;j=0,则 dp1[0][0]=1
  • 如果 i=1zero;j=01 的个数是 0,故 dp1[i][0]=0
  • 如果 i=0;j=1one0 的个数是 0,但只能连续填 limit1,故 dp1[0][0min(one,limit)]=1,其余为 0
class Solution {
    public int numberOfStableArrays(int zero, int one, int limit) {
        int MOD = 1000000007;
        int[][] dp0 = new int[zero + 1][one + 1];
        int[][] dp1 = new int[zero + 1][one + 1];
        for(int i = 0; i <= Math.min(zero, limit); i++)
            dp0[i][0] = 1;
        for(int j = 0; j <= Math.min(one, limit); j++) 
            dp1[0][j] = 1;
        for(int i = 1; i <= zero; i++) {
            for(int j = 1; j <= one; j++) {
                dp0[i][j] = dp1[i - 1][j] + dp0[i - 1][j];
                dp0[i][j] -= i > limit ? dp1[i - 1 - limit][j] : 0;
                // 因为取余后 后面的数可能比前面的数小 故此处不加上 MOD 会导致 dp0[i][j] 变为负数
                dp0[i][j] = (dp0[i][j] % MOD + MOD) % MOD;
                dp1[i][j] = dp0[i][j - 1] + dp1[i][j - 1];
                dp1[i][j] -= j > limit ? dp0[i][j - 1- limit] : 0;
                // 因为取余后 后面的数可能比前面的数小 此处不加上 MOD 会导致 dp1[i][j] 变为负数
                dp1[i][j] = (dp1[i][j] % MOD + MOD) % MOD;
            }
        }
        return (dp0[zero][one] + dp1[zero][one]) % MOD;
    }
}
posted @   Koonan-Edogawa  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示