题目描述:
求出1-13的整数中1出现的次数,并算出100-1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
时间限制:1秒
空间限制:32768K
思路:题目要求求出1-n之间出现1的次数,可以将当前n出现1的次数打表,存放在数组中,这样直接 O(1) 复杂度获取结果即可,时间消耗主要在打表过程中,但是打表一次,后面就可以直接使用数据,所以还是比较高效。递推方程:a[n] = a[n-1] + fun(n); fun方法表示获取当前数 n 中1的次数。
示例代码:
class Solution {
public:
public:
int a[100000];
//获取当前数 x 中 1 的个数
int getNum(int x) {
int cnt = 0;
while (x) {
if (x % 10 == 1) cnt++;
x /= 10;
}
return cnt;
}
//打表
void init(){
a[0] = 0;
for (int i = 1;i < 100000;i++) {
a[i] = a[i-1] + getNum(i);
}
}
int NumberOf1Between1AndN_Solution(int n){
init();
//返回答案
return a[n];
}
};
注意:如果题目中 n 较大,一次打表可能会超时,那么可以分为多次打表,比如先打表 1 - 10^4 ,然后在打表 10^4 - 10^8,这样就不会出现超时。
Java 中可以使用如下暴力方法求解:
public int NumberOf1Between1AndN_Solution(int n) {
StringBuffer buffer = new StringBuffer();
for (int i = 0;i <= n;i++) {
buffer.append(i);
}
int cnt = 0;
String str = buffer.toString();
for (int i = 0;i < str.length();i++) {
if (str.charAt(i) == '1')
cnt++;
}
return cnt;
}
将 1 - n 所有数字全部凑在一起然后遍历求得 1 的个数,虽然暴力,但是也能通过。