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].

Credits:
Special thanks to @memoryless for adding this problem and creating all test cases.

这道题让我们找一个范围内的各位上不相同的数字,比如123就是各位不相同的数字,而11,121,222就不是这样的数字。那么我们根据提示中的最后一条可以知道,一位数的满足要求的数字是10个(0到9),二位数的满足题意的是81个,[10 - 99]这90个数字中去掉[11,22,33,44,55,66,77,88,99]这9个数字,还剩81个。通项公式为f(k) = 9 * 9 * 8 * ... (9 - k + 2),那么我们就可以根据n的大小,把[1, n]区间位数通过通项公式算出来累加起来即可,参见代码如下:

解法一:

class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
if (n == ) return ;
int res = ;
for (int i = ; i <= n; ++i) {
res += count(i);
}
return res;
}
int count(int k) {
if (k < ) return ;
if (k == ) return ;
int res = ;
for (int i = ; i >= ( - k); --i) {
res *= i;
}
return res * ;
}
};

下面这种方法是上面方法的精简版,思路完全一样:

解法二:

class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
if (n == ) return ;
int res = , cnt = ;
for (int i = ; i <= n; ++i) {
cnt *= ( - i);
res += cnt;
}
return res;
}
};

最后我们来看题目提示中所说的回溯的方法,我们需要一个变量used,其二进制第i位为1表示数字i出现过,刚开始我们遍历1到9,对于每个遍历到的数字,现在used中标记已经出现过,然后在调用递归函数。在递归函数中,如果这个数字小于最大值,则结果res自增1,否则返回res。然后遍历0到9,如果当前数字没有在used中出现过,此时在used中标记,然后给当前数字乘以10加上i,再继续调用递归函数,这样我们可以遍历到所有的情况,参见代码如下:

解法三:

class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
int res = , max = pow(, n), used = ;
for (int i = ; i < ; ++i) {
used |= ( << i);
res += search(i, max, used);
used &= ~( << i);
}
return res;
}
int search(int pre, int max, int used) {
int res = ;
if (pre < max) ++res;
else return res;
for (int i = ; i < ; ++i) {
if (!(used & ( << i))) {
used |= ( << i);
int cur = * pre + i;
res += search(cur, max, used);
used &= ~( << i);
}
}
return res;
}
};

参考资料:

https://leetcode.com/discuss/107981/backtracking-solution

https://leetcode.com/discuss/108119/java-concise-dp-solution

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Count Numbers with Unique Digits 计算各位不相同的数字个数的更多相关文章

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

    给定一个非负整数 n,计算各位数字都不同的数字 x 的个数,其中 0 ≤ x < 10n.示例:给定 n = 2,返回 91.(答案应该是除[11,22,33,44,55,66,77,88,99 ...

  2. Leetcode: Count Numbers with Unique Digits

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

  3. LC 357. Count Numbers with Unique Digits

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

  4. [Swift]LeetCode357. 计算各个位数不同的数字个数 | Count Numbers with Unique Digits

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

  5. 【LeetCode】357. Count Numbers with Unique Digits 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  6. 【Leetcode】357. Count Numbers with Unique Digits

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

  7. Java [Leetcode 357]Count Numbers with Unique Digits

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

  8. Count Numbers with Unique Digits -- LeetCode

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

  9. Count Numbers with Unique Digits

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

随机推荐

  1. Android面试一天一题(1Day)

    写在前面 该博客思路源于在简书看到goeasyway博主写的Android面试一天一题系列,无copy之意,仅为让自己总结知识点,成长一点点.先感谢各位大神的无私分享~! 关于题目,大部分则出自And ...

  2. 原生JS实现全屏切换以及导航栏滑动隐藏及显示——重构前

    思路分析: 向后滚动鼠标滚轮,页面向下全屏切换:向前滚动滚轮,页面向上全屏切换.切换过程为动画效果. 第一屏时,导航栏固定在页面顶部,切换到第二屏时,导航条向左滑动隐藏.切换回第一屏时,导航栏向右滑动 ...

  3. Objective-C内存管理之引用计数

    初学者在学习Objective-c的时候,很容易在内存管理这一部分陷入混乱状态,很大一部分原因是没有弄清楚引用计数的原理,搞不明白对象的引用数量,这样就当然无法彻底释放对象的内存了,苹果官方文档在内存 ...

  4. 解决ngnix服务器上的Discuz!x2.5 Upload Error:413错误

    1.修改php.ini sudo nano /etc/php5/fpm/php.ini #打开php.ini找到并修改以下的参数,目的是修改上传限制 max_execution_time = 900 ...

  5. java script第一篇(按钮全选的实现)

    今天刚学了java script,记录下学习新知识的点滴.以下是操作步骤.鉴于我是初级者,如有错误,恳请读者指正.万分谢谢. 1.新建一个文档(用NotePad软件,为了使得在浏览器中打开不是乱码,在 ...

  6. iOS 自定义方法 - UIView扩展

    示例代码 //#import <UIKit/UIKit.h>@interface UIView (LPCView)/** 上 */@property CGFloat top;/** 下 * ...

  7. android ImageLoader 混淆加载drawable出现黑色图片的解决方案

    在网上找了很久,没有找到.后来看了源码才知道... 多线程异步加载和显示图片(图片来源于网络.sd卡.assets文件夹,drawable文件夹(不能加载9patch),新增加载视频缩略图) Stri ...

  8. json相关类库,java对象与json相互转换

    有效选择七个关于Java的JSON开源类库 转自:http://www.open-open.com/lib/view/open1397870197828.html 翻译: (英语原文:http://w ...

  9. java 执行 jar 包中的 main 方法

    java 执行 jar 包中的 main 方法 通过 OneJar 或 Maven 打包后 jar 文件,用命令: java -jar ****.jar执行后总是运行指定的主方法,如果 jar 中有多 ...

  10. 1.2 - C#语言习惯 - 用运行时常量readonly而不是编译期常量const

    C#中有两种类型的常量:编译期常量和运行时常量.二者有着截然不同的行为,使用不当将会带来性能上或正确性上的问题. 这两个问题最好都不要发生,不过若难以同时避免的话,那么一个略微慢一些但能保证正确的程序 ...