【数位DP】leetcode2376. 统计特殊整数

该问题要求计算从1到给定正整数n之间,每个数位都不同的整数(特殊整数)的数量。解决方案采用数位动态规划(DP),通过递归函数f(i,mask,is_limit,is_num)计算在不同状态下的特殊整数个数,其中mask表示已使用的数字,is_limit和is_num控制填充数字的范围。最后返回f(0,0,True,False)作为答案。

题目:

如果一个正整数每一个数位都是 互不相同 的,我们称它是 特殊整数 。

给你一个 正 整数 n ,请你返回区间 [1, n] 之间特殊整数的数目。

示例 1:

输入:n = 20
输出:19
解释:120 之间所有整数除了 11 以外都是特殊整数。所以总共有 19 个特殊整数。

示例 2:

输入:n = 5
输出:5
解释:15 所有整数都是特殊整数。

示例 3:

输入:n = 135
输出:110
解释:从 1135 总共有 110 个整数是特殊整数。
不特殊的部分数字为:22114131

思路:

  • 数位DP
  • 集合说明
    在这里插入图片描述

解答:

class Solution:
    def countSpecialNumbers(self, n: int) -> int:
        s=str(n)
        # 数位DP
        # 返回从i位开始填数字,i前面填的数字的集合是mask,能构造出的特殊整数的个数
        # is_limit 表示前面填的数字是否都是n对应位上的,如果为true,那么当前位至多为int(s[i]),否则为9
        # is_num 表示前面是否填了数字,如果为true,那么当前位可以从0开始;如果为false,那么我们可以跳过,或者从1开始填数字
        @cache
        def f(i,mask,is_limit,is_num):
            if i==len(s):
                return int(is_num)
            res=0
            if not is_num: #选择跳过,不填数字
                res=f(i+1,mask,False,False)
            up=int(s[i]) if is_limit else 9
            #枚举要填的数字,枚举的范围就取决于is_limit 和is_num
            for d in range(1-int(is_num),up+1):
                if mask>>d & 1==0: #mask里面没有d,则d可选
                   res+=f(i+1,mask|(1<<d),is_limit and d==up,True)
            return res
        return f(0,0,True,False) 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值