902. Numbers At Most N Given Digit Set

题目要凑比指定数N小的数字,可以分成两个子问题:1.位数比N少的数字有多少(位数比它少 => 一定比它小);2.位数和N相同、但比它小的数字有多少;

问题1就是个排列计算,问题2可以dp,状态方程很容易看出来:

f(N) = D中比N[0]小的数字*排列数(n-1/d) + f(N[1:])
where n = len(N), d = len(D)

当N缩到9以下的时候,直接返回D中比N小的digit数量就结束。

需要注意的 edge case 是遇到0。

class Solution:
    def atMostNGivenDigitSet(self, D: List[str], N: int) -> int:
        res = 0
        d, n = len(D), len(str(N))
        for i in range(1, n):
            res += d**(i)
        
        memo = dict()
        
        def countSmaller(number):
            if number in memo.keys(): return memo[number]
            if number <= 9:
                memo[number] = len([x for x in D if int(x) <= number])
                return memo[number]
            head, tail = str(number)[0], str(number)[1:]
            sHead = len([x for x in D if int(x) < int(head)])
            sTail = countSmaller(int(tail)) if tail[0] != '0' and head in D else 0
            memo[number] = sHead*(d**(len(str(number))-1)) + sTail
            return memo[number]
        
        res += countSmaller(N)
        
        return res

Last updated

Was this helpful?