力扣3130.找出所有稳定的二进制数组 II随笔

“我觉得坦途在前,人又何必因为一点小障碍而不走路呢?”——鲁迅

题目

给你 3 个正整数 zero ,one 和 limit 。

一个 二进制数组

 arr 如果满足以下条件,那么我们称它是 稳定的 :

  • 0 在 arr 中出现次数 恰好 为 zero 。
  • 1 在 arr 中出现次数 恰好 为 one 。
  • arr 中每个长度超过 limit 的 

    子数组 都 同时 包含 0 和 1 。

请你返回 稳定 二进制数组的  数目。

由于答案可能很大,将它对10^{9}+7取余 后返回。

难度:困难

分析

        笔者本来在做找出所有稳定的二进制数组 Ⅰ(中等题)却觉得异常困难😓,发现这两道题的唯一区别就是数据量,那么就记录这道题吧。不过,笔者的笨方法可以通过Ⅰ,Ⅱ中内存超出限制,所以还是借鉴了官方的题解。

        我们使用dp[zero][one][0]表示含有zero个0,one个1且末尾为0的数组个数,dp[zero][one][1]表示含有zero个0,one个1且末尾为1的数组个数。对于dp[zero][one][0],如果不考虑limit的限制,则当前是0,前面是0或1都可,易知dp[zero][one][0]=dp[zero-1][one][0]+dp[zero-1][one][1],考虑limit,则需要减去添加末尾0后导致数组不稳定的情况,数组从稳定变为不稳定临界情况为之前恰好有limit个0,我们把这些0固定,如果前面还有数组,它的数量为dp[zero-limit-1][one][1](注意末尾是1)。dp[zero][one][1]亦然,不再赘述。

        综上所述可以得到状态转移方程:

dp[zero][one][0]=dp[zero-1][one][0]+dp[zero-1][one][1]-dp[zero-limit-1][one][1]

dp[zero][one][1]=dp[zero][one-1][0]+dp[zero][one-1][1]-dp[zero][one-limit-1][0]

        最后注意边界情况,个数不超过limit为1,否则为0。

解答

class Solution {
public:
    int numberOfStableArrays(int zero, int one, int limit) {
        int MOD=1e9+7;
        vector<vector<vector<int>>> dp(zero+1,vector<vector<int>>(one+1,vector<int>(2)));
        //one为0的边界情况
        for (int i=0;i<=min(zero,limit);i++){
            dp[i][0][0]=1;
        }
        //zero为0的边界情况
        for (int j=0;j<=min(one,limit);j++){
            dp[0][j][1]=1;
        }
        for (int i=1;i<=zero;i++){
            for (int j=1;j<=one;j++){
                //处理末尾为0的情况
                dp[i][j][0]=dp[i-1][j][0]+dp[i-1][j][1];
                if (i>limit){
                    dp[i][j][0]-=dp[i-limit-1][j][1];
                }
                //处理末尾为1的情况
                dp[i][j][1]=dp[i][j-1][0]+dp[i][j-1][1];
                if (j>limit){
                    dp[i][j][1]-=dp[i][j-limit-1][0];
                }
                //取余
                dp[i][j][0]%=MOD;
                if (dp[i][j][0]<0){
                    dp[i][j][0]+=MOD;
                }
                dp[i][j][1]%=MOD;
                if (dp[i][j][1]<0){
                    dp[i][j][1]+=MOD;
                }
            }
        }
        return (dp[zero][one][0]+dp[zero][one][1])%MOD;
    }
};

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值