题目描述
给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。
示例 1:
输入:n = 13
输出:6
示例 2:
输入:n = 0
输出:0
提示:
0 <= n <= 10^9
笔记
(1)若运算数中有double或float,则其他类型数均转换为double型;
(2)若运算数中最长类型为long,则其他类型数均转换为long型;
(2)若运算数中最长类型为int,则char型也转换为int型。算术转换是在运算过程中自动完成的。
思路及代码
给定数n=abcde,假设为m位。求小于等于n的非负整数中数字1的个数,即分别统计小于等于abcde的所有整数的个位(右数第一位)、十位、百位、…、右数第m位数字中数字1的个数,最后计算它们的和即可,下以计算百位数中数字1的个数为例:
假定百位数字为1,则要满足0<=_ _ 1 _ _<=abcde,问题转化为求满足该不等式的数_ _ 1 _ _的取值种数
分三种情况讨论:
-
当c大于1,数“1”前的值可取[0,ab],数“1”后的值可取[0,99],有(ab+1)*100种情况;
-
当c等于1, 数“1”前的值可取[0,ab],数“1”后的值需分情况讨论:
- 若数“1”前的值为[0,ab),则数“1”后的值可取[0,99]
- 若数“1”前的值为ab,则数“1”后的值可取[0,de]
故有ab*100+1*(de+1)种情况;
-
当c小于1(即c=0),数"1"前的值可取[0,ab),数“1”后的值可取[0,99],有ab*100种情况。
上述种数之和即为所求,也即百位数中数字1的个数。
其余位数情况类似。
计算模拟题:
语言:C++
class Solution {
public:
int countDigitOne(int n) {
int ans=0;
long long value=1; //当前数所在位置 后可取值的最大种数。初始当前数为个位,只有一种情况,故value为1
//例如当前数为百位时,其后取值范围最大为[0,99],故value=100
int suffix=0; //c后的数,即de
while(n){
int temp=n%10; //取出当前位置的数,相当于c
int prefix=n/10; //c前的数,即ab
if(temp>1){
ans+=(prefix+1)*value; //(ab+1)*100
}
else if(temp==1){
ans+=prefix*value+(suffix+1); //ab*100+1*(de+1)
}
else{ //temp<1
ans+=prefix*value; //ab*100
}
suffix+=temp*value;
value*=10;
n/=10;
}
return ans;
}
};
遇到的问题
第一次使用int value;运行报错,原因是未考虑value*=10的数值溢出问题(n最大可达109,可进行10次while循环,value最大可达1010,超出int的109),将value的int型改为long long型即可。