求小於等於N的所有正整數裡面包含的1的個數
阿新 • • 發佈:2018-12-27
題目:
已知一個正整數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; }