Number of Digit One
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.
Hint:
- Beware of overflow.
难题的惯例是先上保底做法。逐个数字数1,累加。
虽然知道会TLE,总比空着白板好。
class Solution { public: int countDigitOne(int n) { int ret = 0; if(n <= 0) return ret; for(int i = 1; i <= n; i ++) { ret += countOne(i); } return ret; } int countOne(int n) { int ret = 0; while(n) { if(n % 10 == 1) ret ++; n /= 10; } return ret; } };
下面上标准做法,参考了编程之美。
这题可以扩展为其他进制的情况。
从右到左逐位计数当前位置(记为cur)为1的所有数字。
(1)cur为0时,需要计数的部分为:cur位置为1,然后对于高位0~high-1的每个值,低位遍历0~divisor。
因此总数为high * divisor
(2)cur为1时,需要计数的部分为:除了上述cur为0的部分,再补充cur为1时,低位遍历0~low。
因此总数为high * divisor + low + 1
(3)cur为其他数时,需要计数的部分为:
cur位置为1,然后对于高位0~high的每个值,低位遍历0~divisor。
因此总数为(high + 1) * divisor
class Solution { public: int countDigitOne(int n) { if(n <= 0) return 0; int ret = 0; int base = 10; long long divisor = 1; while(n / divisor) { int high = n / (divisor * base); int cur = n / divisor % base; int low = n - n / divisor * divisor; if(cur == 0) ret = ret + high * divisor; else if(cur == 1) ret = ret + high * divisor + low + 1; else ret = ret + (high + 1) * divisor; divisor *= base; } return ret; } };