计算各个位数不同的数字个数

题目:https://leetcode-cn.com/problems/count-numbers-with-unique-digits/submissions/

给定一个非负整数 n,计算各位数字都不同的数字 x 的个数,其中 0 ≤ x < 10^n 。

1. 首先想到的是暴力版本:从0开始遍历到 10^n,判断每个数字的每一位是否被重复,没有则计数+1; 显然这种方法遇到大量数据时,会超时。时间复杂度 O(10^n);

/**
 * @param {number} n
 * @return {number}
 */
var countNumbersWithUniqueDigits = function(n) {
    let count=0;
    const isRepeat = (numberStr)=>{
        if(numberStr.length===1) return false;
        
        for(let i=0; i

 2. 回溯:所有的数据都是0-9的数字按不同的顺序组合而成。穷举所有可能的组合,检查组合是否为有效数据: 0 开头的只有0,不会是多位数据,数据是否小于10**n; 每遇到一个有效数据,计数器加1;

有效解的判定: 1. 不是以0开头的多位数,2. 数据小于10**n

每个节点的解空间: 0-9中所有没用过的数字

剪枝函数:数据大于等于10**n, 数据是以0开头的多位数

这种方法的时间复杂度是 O(9n)

/**
 * @param {number} n
 * @return {number}
 */
var countNumbersWithUniqueDigits = function(n) {
    let count=-1;
    backTrack = function(cur,dataSource){
        if(Number(cur)>= 10 ** n || cur.indexOf("0")===0 && cur.length>1) return;
        count++;
        dataSource.forEach((data,index)=>{
            backTrack(cur+data, dataSource.filter(number=>number!==data));
        }); 
    }
    backTrack("",[0,1,2,3,4,5,6,7,8,9]);
    return count;
};

据说还有一种算法:Dynamic Programming

1. 阶段划分:1 位数,2位数,  一直到n位数,逐渐增加位数。

2. 每个阶段的状态:i 位不重复的数字组合可能性为:9*(10-(i-1))*(10-(i-2))*(10-(i-3)) *(10-(i-(i-1))); 假设 Dp[i] 表示 i 位数的组合, Dp[i-1] 表示i-1 位数的组合。 那所有可能的组合就是:Dp[i] = 9*(10-(i-1))*(10-(i-2))*(10-(i-3)) *(10-(i-(i-1))) + Dp[i-1] 

3. 初始状态:Dp[0] =1, Dp[1] = 10, Dp[2] = 9 *9 + 10=91;

/**
 * @param {number} n
 * @return {number}
 */
var countNumbersWithUniqueDigits = function(n) {

    let result =1;;
    for(let i=1;i<=n;i++){
        let cur = 9;
        for(let j=1;j

 

 

 

 

你可能感兴趣的:(基础算法)