難度中等28
輸入一個整數 n
,求1~n這n個整數的十進制表示中1出現的次數。
例如,輸入12,1~12這些整數中包含1 的數字有1、10、11和12,1一共出現了5次。
示例 1:
輸入:n = 12 輸出:5
示例 2:
輸入:n = 13 輸出:6
解題思路:剛開始自己用的普通方法,結果時間超限了。
class Solution {
public static int countOne(int n){
int count = 0;
StringBuilder sb = new StringBuilder();
if(n>9){
int temp = n%10;
n = n/10;
sb.append(temp);
}
sb.append(n);
String s = String.valueOf(sb);
for(int i = 0;i<s.length();i++){
if(s.charAt(i) == '1')
count++;
}
return count;
}
public int countDigitOne(int n) {
int sum = 0;
for(int i = 1;i<=n;i++){
sum+=countOne(i);
}
return sum;
}
}
思路是對的,就是方法太low,遇到比較大的數字就會時間超限。
解法二:
dfs(n)表示數字n有多少個1;
我們可以利用這樣的例子進行思考,
假設數字爲1234,則high = 1 pow = 1000 low = 234;
其中當高位爲1的時候的1的個數 234+1(low+1);
然後就是pow中1的個數爲 dfs(pow)
low中1的個數爲 dfs(low)
最後結果就是low+1+dfs(pow)+dfs(low)
假設數字是2234 則high = 2,pow = 1000 low = 234
則可以將數字分成 0 - 999,1000-1999,2000-2234,
在0-999範圍內,dfs(pow-1)
在1000-1999範圍內分爲兩部分
當高位確定是1的時候:就是1的個數就是pow
拋開高位爲1的情況:就是dfs(pow-1)
2000-2234
就是dfs(low)
最後的結果就是
pow+high*dfs(pow-1)+dfs(low)
class Solution {
public int dfs(int n){
if(n<=0)
return 0;
String s = String.valueOf(n);
int high = s.charAt(0) - '0';
int pow = (int)Math.pow(10,s.length()-1);
int low = n-high*pow;
if(high == 1){
return dfs(pow-1)+low+1+dfs(low);
}else{
return pow+high*dfs(pow-1)+dfs(low);
}
}
public int countDigitOne(int n) {
return dfs(n);
}
}