No.71 - LeetCode357 - 数位上数字不相同个数

方法一:

抛开前导零考虑,只要0不是首位,则0与其他数字无异,
所以通过数字长度划分每种情况:

长度为1,第一位可以取0~10,共10种。
长度为2,必须为两位数,则第一位可以取1~9,第二位可以取剩下9种(这时可以取0),9*9共81种。
长度为3,9*9*8。
以此类推。

最后求和即可。

class Solution {
public:
    int countNumbersWithUniqueDigits(int n) {
        if(n==0) return 1;
        int ans = 10;
        int now = 9;
        int key = 9;
        for(int i = 1;i<n;i++){
            now *= key;
            ans += now;
            key --;
        }
        return ans;
    }
};

方法二:

状态转移思路:比较麻烦,通过n位数量来求出n+1位的数量。

如图,每个树分支上权值乘积,再分支求和即是答案。

简单说说这颗二叉树是如何构造的,
靠上的权值是当前位可以取1~9中数的个数,
靠下的权值是当前位取0的个数,
如果出现中间0,则之后不可再分裂。

每位上数字不同的数量

class Solution {
public:
    // n所求树高,level当前树层数,now当前树节点值,flag是否会出现中间0
    int dfs(const int n,int level,int now,bool flag){
        if(level == n) return now;
        if(flag){
            int sum = 1;
            int key = now;
            for(int i=level;i<n;i++){
                sum *= key;
                key--;
            }
            return sum + now*dfs(n,level+1,now-1,true);
        }
        return dfs(n,level+1,9,true) + dfs(n,level+1,1,false);
    }
    int countNumbersWithUniqueDigits(int n) {
        return dfs(n,0,1,false);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值