輸入乙個整數n
,求1~n
這n
個整數的十進位制表示中1
出現的次數。
例如,輸入12
,1~12
這些整數中包含1
的數字有1、10、11
和12,1
一共出現了5
次。
示例 1:
輸入:n = 12示例 2:輸出:5
輸入:n = 13限制:輸出:6
1 <= n < 2^31
注意:
本題與主站 233 題相同:
最直觀的做法,就是累加1 ~ n
中每個整數出現1
的次數,我們可以通過對10
求餘數判斷整數的個位數字是不是1
,如果這個數字大於10
,則除以10
之後再判斷個位數字是不是1
。
遺憾的是tle
了,在上述思路中,我們對每個數字都要做除法和求餘運算,以求出該數字中1
出現的次數。而我們知道,對於乙個數字n
,它有o(l
ogn)
o(logn)
o(logn
)位,如100
有log
10100+1
=3log_100 +1=3
log10
100+
1=3 位,即求乙個數n
有多少位的時間複雜度是o(l
ogn)
o(logn)
o(logn
)的,又我們需要求n
個數字,即n
次,那麼總時間複雜度就是o(n
logn
)o(nlogn)
o(nlog
n),當輸入的n
非常大的時候,需要大量的計算,運算效率不高,導致超時了。
我們假設n = abcdef
,其中等號右邊a
為1~9
中的某個數字,其餘的可為0~9
中某個數字,我們需要做的就是統計每個位上,如個位、十位、百位…上能出現1
的次數的總和。
假設求c
位置為1
的個數:
此時c
左邊和右邊的值分別為lval = ab, rval = def
, 而t = 1000
,表示c
的位置是千位
的位置
此時則有如下兩種情況:
lval
取[0, ab-1]
;右邊可以從0
取到999
,也就是此時c
位置可以出現1000
次1
,我們用t
表示,因為t
就是1000
, 此時res += lval * t
;
lval
取ab
;
舉例 :
假如n = 123456
假設當前計算千位上出現1
的個數,在千位上有_ _x_ _ _
,x
的左邊有12
,右邊有456
當左邊是[0,11]
時,千位上可以為1
,且千位右邊的三位可以是0~999
,即千位上的數字我們固定為1
,左邊是[0-11]
的任意乙個數字時,右邊可以是0~999
,共1000
個選擇,所以千位是1
的個數是12 * 1000
如果左邊是12
了
class
solution
for(
int i = numbers.
size()
-1; i >=
0; i--
)// 左邊
res += lval * t;
// 右邊
面試題43 1 n整數中1出現的次數
輸入乙個整數n,求1 n這n個整數的十進位制表示中1出現的次數。例如,輸入12,1 12這些整數中包含1的數字有1 10 11和12,1一共出現了5次。對於乙個數,每次對10取餘判斷最低位是不是1,就可以得到這個數中1的數量,從1遍歷到n,每個數都這麼做,就可以得到1的總數量了。看劍指offer上的...
面試題43 1 n整數中1出現的次數
求出1 13的整數中1出現的次數,並算出100 1300的整數中1出現的次數?為此他特別數了一下1 13中包含1的數字有1 10 11 12 13因此共出現6次,但是對於後面問題他就沒轍了。acmer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數 從1 到 n 中1...
面試題43 1 n整數中1出現的次數
輸入乙個整數 n 求1 n這n個整數的十進位制表示中1出現的次數。例如,輸入12,1 12這些整數中包含1 的數字有1 10 11和12,1一共出現了5次。示例 1 輸入 n 12 輸出 5 示例 2 輸入 n 13 輸出 6 限制 1 n 2 31 思路 遞迴。將數字分為最高位和後幾位。當數字由1...