https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/
题目描述
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
限制:
1 <= n < 2^31
输入输出样例
输入:n = 12
输出:5
题解
这题如果使用暴力法的话,会在测试用例824883294
超时
class Solution {
public int countDigitOne(int n) {
int count = 0;
for(int i=1; i<=n; i++){
int temp = i;
while(temp > 0){
if(temp % 10 == 1){
count++;
}
temp = temp/10;
}
}
return count;
}
}
这题需要找规律:
给定一个数字 12345 来打比方:
- 固定住
个位
为1,此时高位是1234,低位是0,此时有 1234+1 个。
(多出来的1是1234全为0的情况) - 固定住
十位
为1,此时高位是123,低位是5,此时有1239+1个。
(由于十位上的数字是大于1的,所以最后一位可以取到9) - 固定住
百位
为1,此时高位是12,低位是45,此时有1299+1个。 - 固定住
千位
为1,此时高位是1,低位是345,此时有1999+1个。 - 固定住
万位
为1,此时高位是0,低位是2345,此时有2345+1个。
12045
如果被固定的位数上,原本是0,那么此时就是1199+1了——1200
(只需要计算最高位值)
12145
如果被固定的位数上,原本是1,那么此时就是1245+1了——1246
(需要计算最高位和最低位的值,并加1)
12345
如果被固定的位数上,是其它的,那么此时就是 1299+1了——1300
(需要计算最高位+1值)
代码:
class Solution {
public int countDigitOne(int n) {
int
cur = n % 10, // 当前位
high = n / 10, // 最高位
low = 0, // 最低位
digit = 1, // 同步 位数
count = 0; // 出现次数
// 如果当前位和最高位都是0,说明n==>0了
while(cur != 0 || high != 0){
// 如果被选定的位是0
if(cur == 0) count += (high*digit);
else if(cur == 1) count += (high*digit) + low + 1;
else count += (high+1)*digit;
// 更新变量,注意顺序
low += digit * cur;
cur = high % 10;
high /= 10;
digit *= 10;
}
return count;
}
}