Number of Digit One

hard math dp recursion

Problem

Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.

Inputn = 13
Output6
Ones come from 1, 10, 11, 12, 13 → digits-with-1 count = 1+1+2+1+1 = 6. For each digit position with place value p (1, 10, 100, …), split n into high, cur, low parts and add the contribution at that place.

def count_digit_one(n):
    if n <= 0: return 0
    count, p = 0, 1
    while p <= n:
        high, cur, low = n // (p * 10), (n // p) % 10, n % p
        if cur == 0:   count += high * p
        elif cur == 1: count += high * p + low + 1
        else:          count += (high + 1) * p
        p *= 10
    return count
function countDigitOne(n) {
  if (n <= 0) return 0;
  let count = 0, p = 1;
  while (p <= n) {
    const high = Math.floor(n / (p * 10));
    const cur = Math.floor(n / p) % 10;
    const low = n % p;
    if (cur === 0) count += high * p;
    else if (cur === 1) count += high * p + low + 1;
    else count += (high + 1) * p;
    p *= 10;
  }
  return count;
}
class Solution {
    public int countDigitOne(int n) {
        if (n <= 0) return 0;
        long count = 0, p = 1;
        while (p <= n) {
            long high = n / (p * 10), cur = (n / p) % 10, low = n % p;
            if (cur == 0) count += high * p;
            else if (cur == 1) count += high * p + low + 1;
            else count += (high + 1) * p;
            p *= 10;
        }
        return (int) count;
    }
}
int countDigitOne(int n) {
    if (n <= 0) return 0;
    long long count = 0, p = 1;
    while (p <= n) {
        long long high = n / (p * 10), cur = (n / p) % 10, low = n % p;
        if (cur == 0) count += high * p;
        else if (cur == 1) count += high * p + low + 1;
        else count += (high + 1) * p;
        p *= 10;
    }
    return (int) count;
}
Time: O(log n) Space: O(1)