数位dp(参照力扣灵神)

题目套路

这类题目一般的描述为,在[L,R]区间内满足某个条件的数字的个数
参照:灵神的讲解

模板讲解

数位dp的核心在于空间换时间,利用缓存保存前面部分的状态
数位dp递归函数一般以下的定义:

fun(int i, int mask, bool isLimit, bool isNum)

其中:

  1. i:表示当前遍历到第 i 位
  2. mask 表示前面选过的数字集合,换句话说,第 i 位要选的数字不能在 mask中。
  3. isLimit 表示前面一位数是否到顶,比如题目限制的数字是4321(下标从左边0开始),当我遍历到第1位时,假如此时isLimit = false,说明第 0 位取的数小于4,不妨设选的时3,那么这时第 1 位可以选[0,9],否则如果isLimit = true,说明第 0 位取4,这时第 1 位是能取[0,3],不然就会超过题目要求的范围
  4. isNum表示前一位是否有取值,true代表取了,否则没有取,这个主要是用于防止前导0的出现

模板代码

    int numberOf2sInRange(int n) {
        string str = to_string(n);
        int len = str.size();
        int di[len][limit]; //limit根据题目要求具体取值
        memset(dp, -1, sizeof(dp));
        function<int(int,int,bool,bool)> fun = [&](int i, int mask, bool is_limit, bool pre_fill) ->int {
            if(i==len)  return ......;
            if(!is_limit && pre_fill && dp[i][mask]!=-1)    return dp[i][mask];
            int ret = 0;
            if(!pre_fill)   ret += fun(i+1, time, false, false);
            int up = is_limit ? (str[i]-'0') : 9;
            for(int d=pre_fill?0:1; d<=up; d++) {
                ret += fun(i+1, .....(根据题目选择下一步的状态), is_limit&&d==up, true);
            }      
            if(!is_limit && pre_fill)   
                dp[i][mask] = ret;
            return ret;
        };
        return fun(0, 0, true, false);
    }

例题

  1. 面试题 17.06. 2出现的次数
  2. 1012. 至少有 1 位重复的数字
  3. 2719. 统计整数数目
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值