LeetCode 357 统计各位数字都不同的数字个数[动态规划 排列组合] HERODING的LeetCode之路

LeetCode 357 统计各位数字都不同的数字个数[动态规划 排列组合] HERODING的LeetCode之路,第1张

解题思路:
首先最简单的方法一定是直接找出每个区间内的不同数字个数,因为n的取值只有8个,暴力点每个都算出来switch返回即可,代码如下:

class Solution {
public:
    int countNumbersWithUniqueDigits(int n) {
        switch (n) {
            case 0: return 1;
            case 1: return 10;
            case 2: return 91;
            case 3: return 739;
            case 4: return 5275;
            case 5: return 32491;
            case 6: return 168571;
            case 7: return 712891;
            case 8: return 2345851;
            case 9: return 5611771;
            default : return 8877691;
        }
        return 0;
    }
};

第二种方法是动态规划的方法,说是动态规划,其实也就是每次10k-1——10k区间的位不同数字个数与之前区间的统计加起来,每个区间的数字个数又和排列组合相关,比如一个四位数,那么第一位能取9个数(除了0),第二位能取9个数(除了第一位),第三位取8个数,最后一位取7个数,相乘起来就是该区间的各位数不同的个数了,代码如下:

class Solution {
public:
    int countNumbersWithUniqueDigits(int n) {
        if(n == 0) return 1;
        vector<int> dp(n + 1);
        dp[0] = 1;
        dp[1] = 10;
        for(int i = 2; i <= n; i ++) {
            dp[i] = dp[i - 1] + (dp[i - 1] - dp[i - 2]) * (11 - i); 
        }
        return dp[n];
    }
};

第三种方法直接套用排列组合,在遍历的时候,一个变量存储当前总和,一个变量存储当前的排列组合规律(9*9*8*…*(n-1)),代码如下:

class Solution {
public:
    int countNumbersWithUniqueDigits(int n) {
        int res = 1;
        int choose = 9;
        for(int i = 1; i <= n; i ++) {
            res += choose;
            choose = choose * (10 - i);
        }
        return res;
    }
};

最后一种方法可能大家也猜到了,就是递归的思路,这样短短三行代码就能实现,代码的思路本质上和排列组合相同,代码如下:

class Solution {
public:
    int countNumbersWithUniqueDigits(int n) {
        if(n == 0) return 1;
        if(n == 1) return 10;
        return countNumbersWithUniqueDigits(n - 1) + (countNumbersWithUniqueDigits(n - 1) - countNumbersWithUniqueDigits(n - 2)) * (11 - n);
    }
};

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/584843.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-12
下一篇 2022-04-12

发表评论

登录后才能评论

评论列表(0条)

保存