《劍指offer》 31 整數1出現的次數

2021-10-07 16:28:10 字數 4035 閱讀 3949

題目描述

求出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出現...