Number of Digit One
Problem Statement:Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.
For example:
Given n = 13,
Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.
Solution : Count by digits.
This kind of question takes more of some math rather than brutal force. It's generally a good practice to think about how can we calculate the occurrence of digit 1's at each position. To solve this let's examine some properties at each digit position.
If we are going to examine each digit of a number we need to break them into three segments: (high) curr (low), where high and low can be any arbitrary non-negative number, for example if we have number 13231 and we are looking at the 3rd bit from right to left, then high = 13, curr = 2, low = 31. We are also going to introduce base which is which is of 10's power. The base for this case is 100 which equals 10 ^ (i - 1) if we are looking at (i)th digit.
We are going to describe the three segment with high, curr, low and base for now on.
Let's first consider simple cases, let's say 200, and we are looking at 2nd digit. The possible number 1 occurring at that position is:
We could have 20 occurrences for that. And the formula for that is (high * base). This is the most basic case where the given number happen to be N * base. So how about this case, suppose we have number 1131 and we are still interested in the 2nd digit. Now the possible occurrence of 1's are:
The total number of 1's equals (12 * base) which is (high + 1) * base. How about the number being 1111 will it still hold? The possible occurrences now become:
If we are going to examine each digit of a number we need to break them into three segments: (high) curr (low), where high and low can be any arbitrary non-negative number, for example if we have number 13231 and we are looking at the 3rd bit from right to left, then high = 13, curr = 2, low = 31. We are also going to introduce base which is which is of 10's power. The base for this case is 100 which equals 10 ^ (i - 1) if we are looking at (i)th digit.
We are going to describe the three segment with high, curr, low and base for now on.
Let's first consider simple cases, let's say 200, and we are looking at 2nd digit. The possible number 1 occurring at that position is:
0 010 1 011 2 012 ... 10 110 11 111 ... 19 119
We could have 20 occurrences for that. And the formula for that is (high * base). This is the most basic case where the given number happen to be N * base. So how about this case, suppose we have number 1131 and we are still interested in the 2nd digit. Now the possible occurrence of 1's are:
0010 0011 ... 0110 ... 0119 0210 ... 1110 1119
The total number of 1's equals (12 * base) which is (high + 1) * base. How about the number being 1111 will it still hold? The possible occurrences now become:
0010 0011 ... 0110 ... 0119 0210 ... 1019 1110 1111
This occurrence of 1's equals (10 * base) + 2 which is (high * base + low + 1). How about the number being 1101, the possible occurrences now become:
The occurrence of 1's now becomes (10 * base) which is (high * base) and this is exactly the first simple case we discuss.
We are further prove that if we divide a number by (high) curr (low) we can calculate the possible occurrence of 1 at curr's digit postion with the following equations:
0010 0011 ... 0110 ... 0119 0210 ... 1010 ... 1019
The occurrence of 1's now becomes (10 * base) which is (high * base) and this is exactly the first simple case we discuss.
We are further prove that if we divide a number by (high) curr (low) we can calculate the possible occurrence of 1 at curr's digit postion with the following equations:
occurrence = high * base, where curr == 0 high * base + low + 1, where curr == 1 (high + 1) * base, where curr > 1
So we can have the following implementation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | class Solution { public: int countDigitOne(int n) { if (n <= 0) return 0; int base = 1; int high = n; int low = 0; long long count = 0; while (high) { int curr = high % 10; high = high / 10; printf("%d\t%d\t%d\t%d\n", high, curr, low, base); if (curr == 0) { count += high * base; } else if (curr == 1) { count += (low+1) + high * base; } else { count += (high+1) * base; } low += curr * base; base *= 10; } return count; } }; |
No comments:
Post a Comment