Description of the problem:
Input an integer n, find the number of occurrences of 1 in the decimal representation of n integers from 1 to n. For example, if you enter 12, the numbers including 1 in the integers from 1 to 12 are 1. 10. 11 and 12. 1 appear a total of 5 times.
This is a widely circulated google interview question.
algorithm:
The first idea : Count each number from 1 to n, and add the results of the statistics. Algorithm complexity is O(n)
Another way of thinking : give an example.
Let n=321. but:
The form of 1 in the one's place is XY1, and the sum of the times is 33 (because the possible combination of the ten's place and the hundreds place is 0-32)
The sum of the number of occurrences of 1 in the tens place is more complex, in the form of X1Y, and the value range of X is 0-3. The value range of Y is 0-9. Therefore, X1Y has a common form of 40, that is, the sum of the number of occurrences of 1 in the tens place is 40
Its hundreds place appears in the form of 1XY. Obviously, the value range of XY is 00-99. So the sum of times is 100
So the sum is 100+40+33=173
After analysis, we can get a general formula:
For a digit number n, the sum of the number of occurrences of 1 on the i-th digit from the right (i starts from 0) is: (the number of combinations from i+1 digits to digit-1 digits + 1)*10 to the power of i
Mathematically expressed as
count(i)=[n/pow(10,i+1)+1]*pow(10,i)
sum=∑count(i)
Since the number of digits digit=[logn]+1 (where logn is rounded down), the time complexity is O(logn)
Code:
The first idea:
#pragma once #include<iostream> using namespace std; int Find(int m) { int sum = 0; while (m > 0) { int temp; temp = m % 10; if (temp == 1) sum += 1; m = m / 10; } return sum; } int Count(int n) { int sum = 0; for (int i = 1; i <= n; i++) sum += Find(i); return sum; } void main() { int n; cin >> n; Count(n); cout << Count(n) << endl; system("pause"); }
Another way of thinking:
#pragma once #include<iostream> #include"math.h" using namespace std; int Count(int list[], int n,int digit) { int sum = 0; for (int i = 0; i < digit; i++) sum += (int(n / pow(10, i + 1)) + 1)*(int)pow(10, i); return sum; } void main() { int n; cin >> n; int temp = n; int digit = 1; // n digits while (temp > 0) { if (temp - temp % 10 > 0) digit++; temp = temp / 10; } int* list = new int[digit];//list[i] is the number of n from the i-th digit on the right for (int i = 0; i < digit; i++) list[i] = (n - int(n%(int)pow(10, i))) / (int)pow(10, i) % 10; cout << Count(list, n,digit) << endl; system("pause"); }