标签:
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:
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 == 0) return 1; int res = 0; for (int i = 1; i <= n; ++i) { res += count(i); } return res; } int count(int k) { if (k < 1) return 0; if (k == 1) return 10; int res = 1; for (int i = 9; i >= (11 - k); --i) { res *= i; } return res * 9; } };
下面这种方法是上面方法的精简版,思路完全一样:
解法二:
class Solution { public: int countNumbersWithUniqueDigits(int n) { if (n == 0) return 1; int res = 10, cnt = 9; for (int i = 2; i <= n; ++i) { cnt *= (11 - 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 = 1, max = pow(10, n), used = 0; for (int i = 1; i < 10; ++i) { used |= (1 << i); res += search(i, max, used); used &= ~(1 << i); } return res; } int search(int pre, int max, int used) { int res = 0; if (pre < max) ++res; else return res; for (int i = 0; i < 10; ++i) { if (!(used & (1 << i))) { used |= (1 << i); int cur = 10 * pre + i; res += search(cur, max, used); used &= ~(1 << 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 计算各位不相同的数字个数
标签:
原文地址:http://www.cnblogs.com/grandyang/p/5582633.html