题目:
给定一个非负整数 n,计算各位数字都不同的数字 x 的个数,其中 0 ≤ x < 10n 。
示例:
输入: 2 输出: 91 解释: 答案应为除去11,22,33,44,55,66,77,88,99
外,在 [0,100) 区间内的所有数字。
思路: 动态规划
---- 当 n = 1 时, 只有 0 符合条件, 当 n = 10 时, 0 - 9 符合条件 (10个);
---- 当 n >= 2 时,记 f( n )为 [ 0, 10^n )范围内满足条件的数值个数,记 g( k ) 为 k位数中满足条件的数值个数, 则 f(n) = g(1) + g(2) + g(3) + ... +g(n) = f (n - 1) + g (n),而 g(n) 属于组合问题, g(n) = 9 * 9 * 8 * 7 *...... * (11 - n),第一个“9”代表最高位上可选择的数为“ 1 ~ 9”九个,0 不可选,第二个“9”代表第二位上可选择的数为“0 ~ 9”中除去高位所选的其他九个数,依次类推,第 n 位上可选的数有 ( 11 - n ) 个。
JS实现:
var countNumbersWithUniqueDigits = function (n) { if (n === 0) { return 1; } else if (n === 1) { return 10; }
// 以上不解释 var ret = 10, // 因为f(1) = 10 last_state = 9; // 最后一位有九种选择 for (let i = 1; i < n; i++) { last_state *= (10 - i); // 排列组合, 求阶乘 ret += last_state; // 然后累加
} return ret; }
附上自己想的一看就懂渣代码: 超时..........
var countNumbersWithUniqueDigits = function (n) { let lastNum = 0, obj = {}, num = Math.pow(10, n); if (n === 0) { return 1; } else if (n === 1) { return 10; } for (let i = 0; i < num; i ++) { let stringI = String(i).split(''); console.log(stringI); obj = {}; for (let j = 0, strLen = stringI.length; j < strLen; j ++) { if (obj[stringI[j]]) { lastNum ++; break; } else { obj[stringI[j]] = 1; } } }
return num - lastNum;
}