题目:输入一个int数,求1到到该数中1的次数。
public int countDigitOne(int n)
思路:1.用基本的方法,遍历+每位统计,时间复杂度O(nlog10n),复杂度太大。
2.用每位固定为1,然后看有多少种情况。用找规律的方法来做。时间复杂度为O(log10n),n得到其位数需要log10n次运算。
规律怎么找的?
写一个数字,从digit=10开始分析,当十位为0,1,2~9的时候,把十位固定为1,看看有多少个情况。然后用high,low,digit来得到规律。
- 当前位分为3种情况,分别是0,1和2~9。对应的1的数量和规律不同。
- 把数字分为当前位cur,高位high和低位low,用digit来表示当前的是什么位,digit等于1是当前是个位。
- 然后cur,high,low不断变化,结果不断累积到res上,最后返回。
//思路:通过每位来看该位为1时有多少中情况(固定某一位),用找规律的方式
public int countDigitOne(int n) {
int res = 0;
int temp = n;
//先从个位开始
int high = temp / 10;
int cur = temp % 10;
int low = 0;
int digit = 1;
//循环次数n次,时间复杂度为O(log10n)
while(temp != 0){
if(cur == 0){
res += (high * digit);
}else if(cur == 1){
res += (high * digit + low + 1);
}else{
res += ((high + 1) * digit);
}
//先用旧的cur修改low,否则后面修改cur就用不了了。
low += (cur * digit);
cur = high % 10;
high /= 10;
digit *= 10;
temp /= 10;
}
return res;
}