求小于等于N的所有正整数里面包含的1的个数
题目:
已知一个正整数N,求比N小(包括N)的所有正整数中包含的1的个数。例如N = 12,则包含5个1,分别为1、10、11、12
解答:
最直观最简单的想法是,从1到N对每一个数检查,得出每个数中包含的一的个数,事件复杂度大概是O(N)
1时间复杂度比较高,不是最优算法。一个比1快的算法是:对N的每一位进行检查,得出比N小的正数某一位包含的1的个数总和。比如1234,千位包含234 + 1个1(1000 ~ 1234),百位包含 2 * 100个1(1100 ~ 1199, 100 ~ 199),十位包含13 * 10个1(1210 ~ 1219,1110 ~ 1119,。。。。。。,10 ~ 19),个位包含124 * 1个1(1231,1221,1211,1201,。。。。。。,1)。按照这个思路可以写出代码如下。
代码:
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> using namespace std; int getNumAfterI(char *buf, int i, int len) { int sum = 0; for(int j = i + 1; j < len; j++) sum = sum * 10 + (buf[j] - '0'); return sum + 1; } int NumOf1AfterN(int n) { int sum = 0; int num = 0; char buf[20]; sprintf(buf, "%d", n); int len = strlen(buf); for(int i = 0; i < len; i++) { if(buf[i] > '1') sum += (num + 1) * pow(10, len - i - 1); else if(buf[i] == '0') sum += num * pow(10, len - i - 1); else sum += (num + 1) * getNumAfterI(buf, i, len); num = num * 10 + (buf[i] - '0'); } return sum; } //test int main() { int num; while(1) { cin >> num; cout << NumOf1AfterN(num) << endl; } return 0; }