1. 程式人生 > >劍指offer第32題JS演算法:輸入一個整數n,求從1到n這n個整數的十進位制表示中1出現的次數。例如輸入12,從1到12這些整數中包含1的數字有1,10,11和12,1一共出現了5次

劍指offer第32題JS演算法:輸入一個整數n,求從1到n這n個整數的十進位制表示中1出現的次數。例如輸入12,從1到12這些整數中包含1的數字有1,10,11和12,1一共出現了5次

題目:輸入一個整數n,求從1到n這n個整數的十進位制表示中1出現的次數。例如輸入12,從1到12這些整數中包含1的數字有1,10,11和12,1一共出現了5次

這是我某一次去朋友公司面試試水時出的面試題,結果給我五分鐘我寫了個for迴圈的方法,被狠狠鄙視/哭笑不得

結果回來後好奇就跟同事一起看了看這道題發現也挺有意思的

//引數n為中點數字,且為整數
function result(n){
    //count表示觀察的值(這裡為1)出現的次數,base表示當前迴圈權重,round表示當前要進入迴圈的數和當前數的週期(高位)
    let count = 0,base = 1,round = n
    //當前要進入迴圈的數不小於1時,執行迴圈
    while(round>=1){
//求出當前數基數
        let weight = round % 10
//求出當前數週期(向下取整),並用作下一輪迴圈的數
        round = Math.floor(round / 10)
//當基數小於1(即為0)時,出現次數為當前週期乘以當前權重
if(weight < 1){
            count += round * base
//當基數大於1時,出現次數為當前週期乘以當前權重再加上額外的一次權重
}else if(weight > 1){
            count += (round + 1) * base
//當基數等於1時,出現次數為當前週期乘以當前權重再加上(基數低一位的數值加1,加1是因為從0開始計數)
        } else if(weight === 1){
            count += round * base + (n%base)+1
        }
//本次迴圈完畢後權重乘以10,實現按位數迴圈,達到O(logn)的複雜度
        base *= 10
    }
    //返回最終的出現總次數
    return count
}
改良版:
function result(n,m){
    let count = 0,base = 1,round = n
    while(round>=m){
        let weight = round % 10
        round = Math.floor(round / 10)
        if(weight > m){
            count += (round + 1) * base
        } else if(weight === m){
            count += round * base + (n%base)+1
        } else{
            count += round * base
        }
        base *= 10
    }
    return count
}
n為最大整數,m為要觀察次數的數字