75 lines
2.5 KiB
C++
75 lines
2.5 KiB
C++
// Source : https://leetcode.com/problems/number-of-digit-one/
|
|
// Author : Hao Chen
|
|
// Date : 2015-07-17
|
|
|
|
/**********************************************************************************
|
|
*
|
|
* 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.
|
|
*
|
|
* Beware of overflow.
|
|
*
|
|
**********************************************************************************/
|
|
|
|
/*
|
|
* The idea is:
|
|
*
|
|
* 1) seprate the n to two parts. considering n is `abc`
|
|
*
|
|
* 2) at first, we seprate it to `ab` & `c`, then,
|
|
* c == 0, the # of `1` appears in uints is "ab * 1"
|
|
* c == 1, the # of `1` appears in units is "ab * 1 + 0 + 1" (0 means the number after `c`)
|
|
* c > 1 , the # of `1` appears in units is "(ab+1)*1"
|
|
*
|
|
* 3) at second, we seprate it to `a` & `bc`, then,
|
|
* b == 0, the # of `1` appears in tens is "a * 10"
|
|
* b == 1, the # of `1` appears in tens is "a * 10 + c + 1" (`c` means the number after `b`)
|
|
* b > 1 , the # of `1` appears in tens is "(a+1)*10"
|
|
*
|
|
* 4) at thrid, we seprate it to `` & `abc`, then,
|
|
* a == 0, the # of `1` appears in tens is "0 * 100" ( 0 menas the number before `a`)
|
|
* a == 1, the # of `1` appears in tens is "0 * 100 + bc + 1" (`bc` means the number after `a`)
|
|
* a > 1 , the # of `1` appears in tens is "(0+1)*100"
|
|
*
|
|
*
|
|
* For some examples:
|
|
* 0) n = 5, we have (0+1)*1 = 1 digit 1
|
|
* 1) n = 53, we have (5+1)*1 + (0+1)*10 = 16 digit 1
|
|
* 2) n = 20, we have (2*1) + (0+1)*10 = 12 digit 1
|
|
* 3) n = 21, we have (2*1+0+1) + (0+1)*10 = 13 digit 1
|
|
* 4) n = 13, we have (1+1)*1 + (0*10+3+1) = 6 digit 1
|
|
* 5) n = 109, we have (10+1)*1 + (1*10) + (0*100 + 09 + 1) = 31 digit 1
|
|
*
|
|
* Converting the ideas to code as below:
|
|
*
|
|
*/
|
|
|
|
class Solution {
|
|
public:
|
|
|
|
int countDigitOne(int n) {
|
|
long long base=1, left=n, right=0, currDigit=0;
|
|
int numOfOne = 0;
|
|
while(left>0) {
|
|
currDigit = left % 10;
|
|
left = left/ 10;
|
|
|
|
if (currDigit == 0) {
|
|
numOfOne += (left * base);
|
|
}else if (currDigit == 1) {
|
|
numOfOne += (left * base + right + 1);
|
|
}else {
|
|
numOfOne += ((left+1)*base);
|
|
}
|
|
|
|
right = right + currDigit * base;
|
|
base *= 10;
|
|
}
|
|
return numOfOne;
|
|
}
|
|
};
|