【LeetCode每日一题打卡】357. 统计各位数字都不同的数字个数

165 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

LeetCode每日一题打卡专栏正式启动!不出意外将日更LeetCode的每日一题,敬请期待。

个人博客链接:bbstudy.net/ (等毕业论文做好后续会完善相关功能)

4.11:统计各位数字都不同的数字个数

LeetCode 357,点击题目可直接跳转至LeetCode

题解一:暴力DFS

n最大为8,比较容易想到的思路便是直接通过dfs遍历每一位数字,如果各位数字都不同则记录数+1,最终统计满足条件的个数即可。

注意:前导0的情况需要特判下。

缺点:费时

C++代码:

class Solution {
public:
    map<int,int> mp;
    int ans;
    int check(){
        for(int i=1;i<10;i++) if(mp[i]) return 0;
        return 1;
    }
    void dfs(int cnt,int  n){
        if(cnt>n){
            ++ans;return ;
        }
        for(int i=0;i<10;i++){
            if(mp[i]) continue;
            if(check()&&i==0){ //前面全是前导0
                dfs(cnt+1,n);
            }else{
                mp[i]++;
                dfs(cnt+1,n);
                mp[i]--;
            }
        }
    }
    int countNumbersWithUniqueDigits(int n) {
        mp.clear();
        if(n==1) return 10;
        ans=0;
        dfs(1,n);
        return ans;
    }
};

题解二:排列组合

官方提供的思路。

  • n=0时:,满足条件个数为:1个
  • n=1时:,满足条件个数为:0~9,10个
  • n=2时:,可以由两部分构成:只有一位数的情况和两位数的情况。其中

    • 只有一位数的情况由上述可得x有10种;
    • 有两位数的情况:第一位可以取1-9(9种), 第二位可以取0-9除了和第一位不同的数字(9种),于是就有:9*9=81种。
  • n=3时,可以分为三部分:一位数、两位数、三位数

    • 一位数:10种(0~9)
    • 两位数:9*9=81种
    • 三位数:998
  • 扩展至n>=2:含有n位数字的情况,可以表示为:9*A9n1A_{9}^{n-1}

于是代码如下:

C++代码:

class Solution {
public:
    int countNumbersWithUniqueDigits(int n) {
        if(n==0) return 1;
        else if(n==1) return 10;
        int ans=10,num=9;
        for(int i=1;i<=n-1;i++){
            num*=(9-i+1);   //9*9*8*....
            ans+=num;
        }
        return ans;
    }
};

当然,还有其他的解法,比如:n最大为8,可以直接打表(存储n为0~8的结果);还可以用dp等等,此处并不一一列举。