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

在这里插入图片描述

解题思路:
首先最简单的方法一定是直接找出每个区间内的不同数字个数,因为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);
    }
};

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:技术黑板 设计师:CSDN官方博客 返回首页
评论

打赏作者

HERODING23

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值