902.最大为N的数字组合

902.最大为N的数字组合

我们有一组排序的数字 D,它是 {‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’} 的非空子集。(请注意,‘0’ 不包括在内。)
现在,我们用这些数字进行组合写数字,想用多少次就用多少次。例如 D = {‘1’,‘3’,‘5’},我们可以写出像 ‘13’, ‘551’, ‘1351315’ 这样的数字。
返回可以用 D 中的数字写出的小于或等于 N 的正整数的数目。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/numbers-at-most-n-given-digit-set
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

来自我的LeetCode题解

一道典型的数位动态规划问题,掌握了数位动态规划思想和模板可以秒杀。
这道题有两点需要注意:首先是需要引入前导0,因为0不在可枚举数字的范围内,但是为了满足数字位数要求,0又是必须的;其次是上界的安全,因为枚举的数字是1到9的子集,所以枚举的时候只能在子集中枚举,这里的代码采用先枚举再验证的写法;最后是不要钻牛角尖,这里limit的判断与模板一样,这里很难表达,建议读者自己思考。

class Solution {
    
    
    private int[][][] dp = null;
    private int[] upperBound = null;
    private List<Integer> list = null;
    
    public int atMostNGivenDigitSet(String[] digits, int n) {
    
    
        list = new ArrayList<>();
        for(String digit : digits) {
    
    
            list.add(Integer.valueOf(digit));
        }
        String string = String.valueOf(n);
        char[] chars = string.toCharArray();
        int length = chars.length;
        upperBound = new int[length];
        for(int i = 0; i < length; ++i) {
    
    
            upperBound[i] = chars[length - 1 - i] - '0';
        }
        dp = new int[length][2][2];
        for(int i = 0; i < length; ++i) {
    
    
            for(int j = 0; j < 2; ++j) {
    
    
                Arrays.fill(dp[i][j], -1);           
            }          
        }
        return this.dfs(length - 1, 1, 1);//最高位数字默认有前导0
    }

    private int dfs(int pos, int limit, int zero) {
    
    //0不在可选数字范围,但是为了补足数字位数,需要前导0
        if(pos == -1) return (zero == 1) ? 0 : 1;
        if(dp[pos][limit][zero] != -1) return dp[pos][limit][zero];
        int maxNum = (limit == 1) ? upperBound[pos] : 9; 
        int res = 0;
        for(int i = 0; i <= maxNum; ++i) {
    
    
            if(zero == 1 && i == 0) {
    
    //当当前第pos位数字有前导0,且当前第pos位数字为0时,第pos-1位数字才有前导0
                res += dfs(pos - 1, (limit == 1 && i == maxNum) ? 1 : 0, 1);  
            }
            else if(list.contains(i)) {
    
    //这里的条件判断保证了上界的安全,需要理解,难以表达
                res += dfs(pos - 1, (limit == 1 && i == maxNum) ? 1 : 0, 0);
            }
        }
        return dp[pos][limit][zero] = res;
    }
}

猜你喜欢

转载自blog.csdn.net/m0_55570281/article/details/114156305