題目描述
求出1-13的整數中1出現的次數,並算出100-1300的整數中1出現的次數?為此他特別數了一下1-13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。acmer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數(從1 到 n 中1出現的次數)。
整數1出現的次數
1 、不考慮時間效率的解法很好理解,可以直接完成
class
solution
:def
numberof1between1andn_solution
(self, n)
:# write code here
ret =
0for i in
range
(n+1):
for s in
str(i)
:if s ==
'1':
ret +=
1return ret
2、另一種思路-找規律
1位數,1-9中,1一共出現了1次;
2位數,10-99中,10-19的十位上一共出現了101=10次,對於每個十位開頭的數字10-19、20-29,每個數個位上出現的是1-9中1出現的次數,共有9個區間91=9次;
3位數,100-999,100-199百位上出現了10**2=100次,對於每個百位數開頭,例如100-199,200-299,低位上其實就是0-99這個區間上1出現的次數,一共9個區間 9*19=171次;
由此推測,對於1-9,10-99,100-999,每個n位數中包含1的個數公式為:
f(1) = 1
f(2) = 9 * f(1) + 10 ** 1
f(3) = 9 * f(2) + 10 ** 2
f(n) = 9 * f(n-1) + 10 ** (n-1)
通過以上分析,我們可以確定對於任意乙個給定的數,例如23456這個5位數,10000之前的數中包含的個數是確定的了,為f(1)+f(2)+f(3)+f(4),這是乙個遞迴的過程,對此可以求出1-4位中包含1的總數,函式如下所示:
def
get_1_digits
(n):
""" 獲取每個位數之間1的總數
:param n: 位數
"""if n <=0:
return
0if n ==1:
return
1 current =
9* get_1_digits(n-1)
+10**(n-1)
return get_1_digits(n-1)
+ current
通過上面的分析,我們知道了23456中,1-10000之間一共出現了多少個1.下一步需要分析10000-23456中包含的1
我們首先把最高位單獨拿出來分析一下,求出最高位上1的個數,如果最高位是1,則最高位上一共會出現的1的次數是低位上數字+1,例如12345,最高位上一共出現了2346個1;如果最高位大於1,則會一共出現的次數是10000-19999一共10**4個數。
然後,根據最高位的不同,計算出該高位前面的相同位數範圍中的所有數中1的個數。例如對於34567,需要計算出10000-19999,20000-29999中一的個數,這時候計算一的個數,也就是計算0-9999中1的個數,這就可以轉化成上面的f(n)來計算了,呼叫上面函式可以直接得到,然後用得到的值和最高位和1的差值(這裡最高位是3)相乘就可以了。
分析完上面的部分後,我們現在只剩下最高位後面的部分了,我們發現剩下的部分還是乙個整數,例如23456剩下了3456,這時候直接使用遞迴處理剩下的3456就行了。具體**如下:
def
allnums
(n):
if n ==0:
return0if
0return
1 digit = get_digits(n)
high =
int(
str(n)[0
])low = n - high*
10**
(digit-1)
low_nums = pre(digit -1)
#最高位之前的1的個數
if high ==1:
high_nums = low +
1 all_nums = high_nums
else
: high_nums =
10**
(digit-1)
all_nums = high_nums + low_nums*
(high -1)
return low_nums + all_nums + allnums(low)
對於上面使用的get_digits函式,是用來求給定的n是幾位數的。**如下:
def
get_digits
(n):
a =0if n ==0:
return
0while n:
n //=
10#整除
a +=
1return a
放一起:
class
solution
:def
numberof1between1andn_solution
(self, n)
:# write code here
# 法一
# ret = 0
# for i in range(n+1):
# for s in str(i):
# if s == '1':
# ret += 1
# return ret
# 法二
defget_digits
(n):
a =0if n ==0:
return
0while n:
n //=
10 a +=
1return a
defpre(n)
:if n ==0:
return
0if n ==1:
return
1 nums =
10**
(n-1
)+ pre(n-1)
*9return nums + pre(n-1)
defallnums
(n):
if n ==0:
return0if
0return
1 digit = get_digits(n)
high =
int(
str(n)[0
])low = n - high*
10**
(digit-1)
low_nums = pre(digit -1)
#最高位之前的1的個數
if high ==1:
high_nums = low +
1 all_nums = high_nums
else
: high_nums =
10**
(digit-1)
all_nums = high_nums + low_nums*
(high -1)
return low_nums + all_nums + allnums(low)
return allnums(n)
**python解決 從1到n整數中1出現的次數 《劍指Offer》31 整數中1出現的次數
題目 31.整數中1出現的次數 知識點 優化 題目描述 求出1 13的整數中1出現的次數,並算出100 1300的整數中1出現的次數?為此他特別數了一下1 13中包含1的數字有1 10 11 12 13因此共出現6次,但是對於後面問題他就沒轍了。acmer希望你們幫幫他,並把問題更加普遍化,可以很快...
劍指offer 31 整數中1出現的次數
1.題目描述求出1 13的整數中1出現的次數,並算出100 1300的整數中1出現的次數?為此他特別數了一下1 13中包含1的數字有1 10 11 12 13因此共出現6次,但是對於後面問題他就沒轍了。acmer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數 從1 ...
整數中1出現的次數(劍指offer 31)
求出113的整數中1出現的次數,並算出1001300的整數中1出現的次數?為此他特別數了一下1 13中包含1的數字有1 10 11 12 13因此共出現6次,但是對於後面問題他就沒轍了。acmer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數 從1 到 n 中1出現...