題目描述
求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?爲此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數(從1 到 n 中1出現的次數)。
那種簡單的嵌套雙遍歷這裏就不講了,說一下另一種思路,使用歸納法總結套路公式老解決。
1、個位1出現的次數:
個位來說1出現的次數會每隔10出現一次,1、11、21、31...所以個位1出現的次數爲n/10,但是輸入的數字可能不是像1、11這種理想的數字可能會多出一部分,如題目所述的13,這時候如果多出來了11~13可能就需要單獨算出來,然後累加到前面的結果。所以有:
k=n%10;
count = n/10+ if(k!=0)1 else 0
2、十位1出現的次數:
十位爲每隔100位數出現一次,10,110,210...所以十位1出現的次數爲n/100,同上,如果出現多出的情況,則需要累加多餘的符合條條件的結果,得出:
k=n%100;
count = (n/100)*10+if(k>19) 10 else if(k<10) 0 else k -10+1
3、百位1出現的次數:
百位每隔1000位數出現一次,100,1100,2100...所以百位1出現的次數n/1000,跟個位相同,出現多出的情況,則累加:
k=n%1000;
count = (n/1000)*100+if(k>199) 100 else if(k<100) 0 else k -100+1
通過上邊我們可以總結出:
i範圍爲10~log10(n)
k=n%(10*i)
count = (n/(10*i))*i+if(k>10*i-1) i else if(k<0)0 else k-i+1
最後使用Math的min與max替換if else的操作
import java.util.*;
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
if(n<=0)return 0;
int count = 0;
for(long i =1;i<=n;i*=10){
long tem = i*10;
count +=(n/tem)*i + Math.min(Math.max(n%tem-i+1,0),i);// 保證k-i+1在[0,1]內,其實就是用Math替換掉了if和else if
}
return count;
}
}