← Static tasks

233. Number of Digit One

leetcode hard

#csharp#hard#intervals#leetcode#math

Task

Дано целое число n, посчитайте общее количество единиц, встречающихся во всех неотрицательных числах, меньших или равных n.

Пример

Input: n = 13

Output: 6

C# solution

matched/original
public class Solution {
    public int CountDigitOne(int n) {
        int countr = 0;
        for (long i = 1; i <= n; i *= 10) {
            long divider = i * 10;
            countr += (n / divider) * i + Math.Min(Math.Max(n % divider - i + 1, 0), i);
        }
        return countr;
    }
}

C++ solution

auto-draft, review before submit
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
    public int CountDigitOne(int n) {
        int countr = 0;
        for (long i = 1; i <= n; i *= 10) {
            long divider = i * 10;
            countr += (n / divider) * i + min(max(n % divider - i + 1, 0), i);
        }
        return countr;
    }
}

Java solution

matched/original
public class Solution {
    public int countDigitOne(int n) {
        int countr = 0;
        for (long i = 1; i <= n; i *= 10) {
            long divider = i * 10;
            countr += (n / divider) * i + Math.min(Math.max(n % divider - i + 1, 0), i);
        }
        return countr;
    }
}

JavaScript solution

matched/original
function countDigitOne(n) {
    let countr = 0
    for (let i = 1; i <= n; i *= 10) {
        let divider = i * 10
        countr += Math.floor(n / divider) * i + Math.min(Math.max(n % divider - i + 1, 0), i)
    }
    return countr
}

Python solution

matched/original
def countDigitOne(n: int) -> int:
    countr = 0
    i = 1
    while i <= n:
        divider = i * 10
        countr += (n // divider) * i + min(max(n % divider - i + 1, 0), i)
        i *= 10
    return countr

Go solution

matched/original
func countDigitOne(n int) int {
    countr := 0
    for i := int64(1); i <= int64(n); i *= 10 {
        divider := i * 10
        countr += int(int64(n)/divider)*int(i) + int(min(max(int64(n)%divider-i+1, 0), i))
    }
    return countr
}

func min(a, b int64) int64 {
    if a < b {
        return a
    }
    return b
}

func max(a, b int64) int64 {
    if a > b {
        return a
    }
    return b
}

Explanation

Algorithm

Итерация по степеням 10: Итеративно увеличивайте значение i от 1 до n, увеличивая i в 10 раз на каждом шаге. Это позволяет анализировать каждую цифру числа n.

Подсчет групповых единиц: Для каждой итерации добавляйте (n / (i * 10)) * i к счетчику countr, что представляет собой количество единиц, встречающихся в группах размера i после каждого интервала (i * 10).

Добавление дополнительных единиц: Для каждой итерации добавляйте min(max((n % (i * 10)) - i + 1, 0), i) к счетчику countr, что представляет собой дополнительные единицы, зависящие от цифры на позиции i.

😎