概述
给定一个整数 n,计算所有小于等于 n 的非负数中数字1出现的个数。
例如:
给定 n = 13,
返回 6,因为数字1出现在下数中出现:1,10,11,12,13。
思路:从数的最高位依次计算1出现的次数,对于每整位出现的次数可事先用备忘录记录,避免重复计算
例如:
1.数字150,先计算51-149出现1的次数,那么在百位上,出现的次数应该是49+1次(还有150也要算进去);
然后计算剩余两位,那么就是51-149之间出现的1的次数(忽略百位,已经计算过),这时候结果跟01-99是一样的:考察个位和十位,容易得出这两位1出现的次数都是10次,就可以用备忘录直接得出count(01-99)
2.如果首位数字大于1,例如250,那么count(1-250) = count(1-199) + count(1-50)
其中count(1-199)= 2*count(1-99) + 100 ,其中count(1-99)已经存在备忘录中,另外100次的来源是计算100-199时,百位出现了100次1
static Map<Integer, Integer> map = new HashMap<Integer, Integer>();
static{
map.put(99, 20);
map.put(199, 140);
map.put(299, 160);
map.put(999, 300);
map.put(9999, 4000);
map.put(99999, 50000);
map.put(999999, 600000);//一百万
map.put(9999999, 7000000);
map.put(99999999, 80000000);//一亿
map.put(999999999, 900000000);
map.put(2000000000, 1899999999);//十亿零1到20亿
}
static int count = 0;
public int countDigitOne(int n) {
if(n < 1){
return 0;
}
if(n < 100){
return countDigitOneInN(n);
}
count = 0;
String str = n+"";
int len = str.length();
while(len > 1){
int pow = (int) Math.pow(10,len-1);
int divNum = n / pow;
if(divNum == 1){
count += map.get(pow - 1) + n%(pow) + 1;
}
else{
count += map.get(pow - 1) * (divNum) + (n-n%pow)/divNum;
}
n %= pow;
if(n < 100){
return count + countDigitOneInN(n);
}
str = n+"";
len = str.length();
}
return count;
}
public int countDigitOneInN(int n) {
int count = 0;
for (int i = 1; i <= n; i++) {
int temp = i;
while (temp != 0) {
if (temp % 10 == 1) {
count++;
}
temp /= 10;
}
}
return count;
}
最后
以上就是靓丽白云为你收集整理的leetcode 233. 数字1的个数(Number of Digit One)的全部内容,希望文章能够帮你解决leetcode 233. 数字1的个数(Number of Digit One)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复