1. 程式人生 > >劍指Offer——面試題31:整數中1出現的次數

劍指Offer——面試題31:整數中1出現的次數

整數中1出現的次數(從1到n整數中1出現的次數)

題目:求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?為此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數(從1 到 n 中1出現的次數)。

輸入:13

輸出:6

思路:舉一個例子來分析,就比較清晰了,比如1~2573中5出現的次數,我們從個位、十位然後依次分析。
對於2573的個位中會出現多少個5,主要看它前面有多少數字,即2573 / 10 = 257個,那麼就會出現257個5,因為從0開始,0~256,對於2573由於個位數小於5,所以只有257個


對於十位來說,因為它前面有2573 / 100 = 25個,而且每個十位的5,會有50~59這10個,所以總的來說,十位的5就是 2573 / 100 * 10 = 250個5,又因為7 > 5,所以 2550~2559,這裡還有10個沒算,於是就是 (2573 / 100 + 1)* 10,十位有260個5
對於百位來說,因為它前面有 2573 / 1000 = 2個,而且每個百位的5,會有500~599這100個,所以,百位的5就是 2573 / 1000 * 100 = 200個,又因5 == 5,所以對於2573來說,還有2500~2573這74個5,即(2573 / 1000 * 100) + (2573 % 100 + 1)
對於千位來說,它前面沒有值,即2573 / 10000 = 0。而且千位是2 < 5,所以千位沒有5

總共就是 257 + 260 + 274 個5,所以可以看出每一位即和前面有關係,又和後面有關係,前面有n個數,就是n * pow(10, 該位(個位是0,依次類推))。後面的話主要看該位數字是否大於想累計的數字,如果是就多加 1 * pow(10, 該位(個位是0,依次類推)),如果相等,就看該位後面有多少數,比如有m,就再加個(m+1),因為從0開始計數。如果小於,就不用做任何操作

下面程式碼中currentNumber表示1~n的整數中某個數字出現的次數,比如currentNumber=5,就是1~n中5出現的次數。

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int
n) { int currentSum = 0; int bitNum = 0; int number = n; int currentNumber = 1; while (number > 0) { int num = number % 10; currentSum += (number / 10) * pow(10, bitNum); if (num > currentNumber) { currentSum += pow(10, bitNum); } else if (num == currentNumber) { int temp = n % (int)pow(10, bitNum) + 1; currentSum += temp; } number = number / 10; bitNum++; } return currentSum; } };