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

题目:

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

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

示例 1:

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

示例 2:

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

示例 3:

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

思路:

  • 数位DP
  • 集合说明
    【数位DP】leetcode2376. 统计特殊整数_第1张图片

解答:

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) 

你可能感兴趣的:(leetcode,Python,动态规划,算法,leetcode)