LeetCode #357 - Count Numbers with Unique Digits - Medium

Problem

Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n.

Hint:

  • A direct way is to use the backtracking approach.

  • Backtracking should contains three states which are (the current number, number of steps to get that number and a bitmask which represent which number is marked as visited so far in the current number). Start with state (0,0,0) and count all valid number till we reach number of steps equals to 10n.

  • This problem can also be solved using a dynamic programming approach and some knowledge of combinatorics.

  • Let f(k) = count of numbers with unique digits with length equals k.

  • f(1) = 10, …, f(k) = 9 * 9 * 8 * … (9 - k + 2) [The first factor is 9 because a number cannot start with 0].

Example

Given n = 2, return 91. (The answer should be the total numbers in the range of 0 ≤ x < 100, excluding [11,22,33,44,55,66,77,88,99])

Algorithm

整理一下题意:给定一个非负整数n,计算[0,10^n)上的所有的各位不相同的数的数目。例如234、378就是各位不相同的数;22、696、990就不是各位不相同的数。

根据提示,可以通过回溯的方法求解,也可以通过递推公式的方法求解。显然后者会更简单,于是尝试从数学的角度推导递推公式。

设x为[0,10^n)上的任意一个数,count为当[0,10^n)上的所有的各位不相同的数的数目。n=0时,x=0,count=1;当n=1时,x为0,1,2,…,10,count=10。上面两种情况,区间内所有取值都是各位不相同的数。

下面设f(k)为有一个k位数包含各位不相同的数的数目,其中k>=2。对于k位数,

  • 左边第1位取值,由于一个两位数最高位不能为0,可取1-9,因此有9种取法;
  • 左边第2位取值,可以取0,除去第k-1位所用数字不能取外,还有9种取法;
  • 左边第3位取值,同理,有8种取法 ;
  • …;
  • 左边第k位取值,有9-k+2取法,直到0-9这10种不同的数字都取完。

于是,

f(k)= 9 * 9 * 8 * ... (9 - k + 2) , k>=2

根据以上递推公式,代码如下。

//递推版本,时间复杂度O(n)
class Solution {
public:
    int countNumbersWithUniqueDigits(int n) {
        if(n==0) return 1;
        if(n==1) return 10;

        int count=10;
        int f=9;
        for(int k=2;k<=n;k++){
            f*=(9-k+2);
            count+=f;
        }
        return count;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值