题目:
输入一个整数n,求1~n这n个整数的十进制表示中1出现的次数。例如,输入12,1~12这些整数中包含1的数字有1、10、11和12,1一共出现了5次。
分析:
不考虑时间效率的解法,靠它想拿Offer有点难
对于一个数,每次对10取余判断最低位是不是1,就可以得到这个数中1的数量,从1遍历到n,每个数都这么做,就可以得到1的总数量了。
从数字规律着手明显提高时间效率的解法,能让面试官耳目一新
看剑指Offer上的内容没看懂,在网上找讲解的时候,看到了《编程之美》里的解释,大概能理解了,引用过来。
设N=abcde,其中abcde分别为十进制中各位上的数字,以计算百位上1出现的次数为例来分析。百位上出现1的情况,受到3方面的影响:百位上的数字、百位以下(低位)的数字、百位以上(高位)的数字。
- 如果百位上的数字为0,百位上出现1的次数由高位决定。比如:12013,百位上出现1的情况可能是:100~199,1100~1199,2100~2199,……,11100~11199,一共1200个。可以看出是由高位(12)决定,并且等于高位(12)乘以当前位数(100)。注意:高位不包括当前位。
- 如果百位上的数字是1,百位上可能出现1的次数不仅受到高位影响还受到低位影响。比如:12113,受高位影响的结果是1200个。再看受低位的影响,百位出现1的情况是12100~12113,一共14个,等于低位数字(13)+1。注意:低位不包括当前位。
- 如果百位数字大于1(2~9),则百位上出现1的情况仅受高位影响。比如,12213,百位出现1的情况是:100~199,1100~1199,2100~2199,……,11100~11199,12100~12199,一共有1300个,并且等于更高位数字+1(12+1)乘以当前位数(100)。
解法:
不考虑时间效率的解法,靠它想拿Offer有点难
package com.wsy;
public class Main {
public static void main(String[] args) {
int n = 20;
getTotalNumberOf1(n);
}
public static void getTotalNumberOf1(int n) {
int count = 0;
for (int i = 1; i <= n; i++) {
count += getNumberOf1(i);
}
System.out.println("1的总个数:" + count);
}
public static int getNumberOf1(int n) {
int count = 0;
while (n != 0) {
if (n % 10 == 1) {
count++;
}
n /= 10;
}
return count;
}
}
从数字规律着手明显提高时间效率的解法,能让面试官耳目一新
package com.wsy;
public class Main {
public static void main(String[] args) {
int n = 21345;
getCountOf1(n);
}
public static void getCountOf1(int n) {
if (n < 0) {
return;
}
int i = 1;
int count = 0;
while (n / i != 0) {
int high = n / (10 * i);// 高位
int current = n / i % 10;// 当前位
int low = n - (n / i) * i;// 低位
if (current == 0) {
count += high * i;
} else if (current == 1) {
count += high * i + low + 1;
} else {
count += (high + 1) * i;
}
i *= 10;
}
System.out.println("1到" + n + "有" + count + "个1");
}
}