357. Count Numbers with Unique Digits统计各位不同的数字个数

Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n.
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])
Hint:
  1. A direct way is to use the backtracking approach.
  2. 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.
  3. This problem can also be solved using a dynamic programming approach and some knowledge of combinatorics.
  4. Let f(k) = count of numbers with unique digits with length equals k.
  5. f(1) = 10, ..., f(k) = 9 * 9 * 8 * ... (9 - k + 2) [The first factor is 9 because a number cannot start with 0].
给定非负整数n,要求在0到10^n的范围内(左闭右开),统计所有各位不相同的数字的个数。


思路
简单地数学分析一下:
设在p中取q进行排列的排列数为P(p,q),本题所求结果为A(n),容易得到以下结果:
  • n = 0, 0 ≤ x < 1 with unique digits is 0, A(0) = 1
  • n = 1, 0 ≤ x < 10 can be divided into
          0本身:0 ≤ x < 1 (0本身) : A(0) = 1
          1位数:1 ≤ x < 10 (10个数取一个) :
          所以A(1) = P(10,1) - 1
  • n = 2, 0 ≤ x < 100 with unique digits can be divided into
          0本身:0 ≤ x < 1 (0本身): A(0) = 1
1位数:1 ≤ x < 10 (10个数取一个): A(1) = P(10,1) - 1
          2位数:10 ≤ x < 100 (10个数取两个,不放回进行排列,但要去掉0开头的数):
          所以A(2) = P(10,2) - P(9,1)
  • n>10,根据抽屉原理,一定存在至少两位有一样的数字,不满足题意,A(n)=0
  • n≤10,相当于10个数取n个不放回进行全排列,去掉0开头的,则A(n)=P(10,n)-P(9,n-1)=9*P(9,n-1)
  • 最后可得结果为分段函数
A(n) = 1                     (n = 0)
A(n) = 9 * P(9,n-1)      (0 < n ≤ 10)
            A(n) = 0                     (n > 10)

class Solution {
public:
    int permutation(int n, int r)
    {
        if(r == 0)
        {
            return 1;
        }else{
            return n * permutation(n - 1, r - 1);
        }
    }
    int countNumbersWithUniqueDigits(int n) {
        int sum = 1;
        if(n > 0)
        {
          int end = (n > 10)? 10 : n;
          for(int i = 0; i < end; i++)
          {
              sum += 9 * permutation(9, i);
          }
        }
        return sum;
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值