Marked as mathematics problem, but if you are able to divide 1s into several cases, the AC code becomes natural.
class Solution { unordered_map<long long, int> memo; public: int countDigitOne(int n) { if (n < 10) return n < 1 ? 0 : 1; if (memo.find(n) != memo.end()) return memo[n]; int base = pow(10, floor(log10(n))); int v = n / base; int r = n % base; int cnt0 = countDigitOne(base - 1); int cnt1 = 0; if (v == 1) { cnt1 = r + 1; } else { cnt1 = base + cnt0; cnt1 += (v - 2) * cnt0; } int ret = cnt0 + cnt1 + countDigitOne(r); memo[n] = ret; return ret; } };
Lesson learnt: visualization in mind is always helpful.
And this link is amazing: https://leetcode.com/discuss/44281/4-lines-o-log-n-c-java-python - Count it digit by digit.