劍指offer29 從1到n整數中1出現的個數

2021-07-13 13:02:52 字數 2302 閱讀 6959

例如輸入12 ,從1 到12 這些整數中包含1 的數字有1、10、11 和12,1 一共出現了5 次。

第一種:不誇慮時間效率的解法

累加1 到n 中每個整數1 出現的次數。我們可以每次通過對10 求餘數判斷整數的個位數字是不是1 。如果這個數字大於10,除以10 之後再判斷個位數字是不是1 。

第二種:從數字規律著手明顯提高時間效率的解法

21345 作為例子來分析。我們把從1 到21345 的所有數字分為兩段, 一段是從1 到1345,另一段是從1346 到21345。

我們先看從1346 到21345 中1 出現的次數。1 的出現分為兩種情況。首先分析1出現在最高位(本例中是萬位)的情況。從1346 到21345 的數字中, 1出現在10000~19999 這10000 個數字的萬位中, 一共出現了10000(10^4)個。

值得注意的是, 並不是對所有5 位數而言在萬位出現的次數都是10000 

個。對於萬位是1 的數字比如輸入12345, 1 只出現在10000~ 12345 的萬位,出現的次數不是10^4 次,而是2346 次,也就是除去最高數字之後剩下的數字再加上1 (即2345+1=2346 次)。

接下來分析1出現在除最高位之外的其他四位數中的情況。例子中1346~21345 這20000 個數字中後4 位中1 出現的次數是2000 次。由於最 

高位是2,我們可以再把1346~21345 分成兩段, 1346~11345 和1 1346~21345 。每一段剩下的4 位數字中, 選擇其中一位是1 ,其餘三位可以在0~9 這10 個數字中任意選擇,因此根據排列組合原則,總共出現的次數是2*4*10^3=8000

至於從l 到1345 中1 出現的次數,我們就可以用遞迴求得了。這也是我們為什麼要把1~21345 分成1~ 1 345 和1346~21345 兩段的原因。因為把21345 的最高位去掉就變成1345 ,便於我們採用遞迴的思路,這樣下次遞迴的時候就可以捨棄最高位2,直接衝1開始了。

採用第二種思路:也就是分拆遞迴的思路。

package 劍指offer;

/*題目:輸入乙個整數n求從1 到n這n個整數的十進位制表示中1 出現的次數。

例如輸入12 ,從1 到12 這些整數中包含1 的數字有1、10、11 和12,1 一共出現了5 次。

*/public class test32

return numberof1(number, 0); }

// 判斷字元陣列number從currentid位置開始包含1的個數

public static int numberof1(int number, int currentid)

int length = number.length - currentid;

// 記錄第乙個位置的也就是數字最高位的元素

int first = number[currentid];

// 用於記錄最高位包含1時的總數

int numfirst = 0;

if (length == 1 && first == 0)

// 如果只有一位且這一位不是0返回1

if (length == 1 && first > 0)

if(first == 1)else if(first > 1)

// numother是[1346, 21345]中,除了第一位之外(不看21345中的第一位2)的數字中的1的數目

int numother = first * (length - 1) * powerbase10(length - 2);

// numrecur是1-1234中1的的數目,這個使用迭代的方式來實現

int numrecur = numberof1(number, currentid + 1);

return numfirst + numother + numrecur; }

public static int powerbase10(int n)

return result;

}private static int atoi(int numbers, int i)

return result;

} public static void main(string args)

}

收穫:1、string value = num + 「」;可以將整形轉化成字串

2、num = char - 『0』;的方式可以將char轉換成數字,其依據是acsii碼表轉換

3、加深理解遞迴的思想。

劍指Offer (29)最小的k個數

題目描述 輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4。實現如下 測試用例中給出的返回值是有序的。嘖嘖。找到序列中最小的k個數,利用set,對數字進行insert或erase 紅黑樹中查詢 插入 刪除操作都為 o logk 最...

劍指offer 29 最小的K個數

題目 輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,思路分析 簡單思路 先快排,再取數 coding utf 8 class solution def getleastnumbers solution self,tinput,...

劍指offer 29 最小的K個數

輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4。最簡單容易想到的就是先排序,然後輸出前k個數即可。但是這樣明顯時間複雜度比較高。也可以使用另外的方法,具體不再詳述。class solution for int i 0 i inp...