LeetCode Entry

440. K-th Smallest in Lexicographical Order

22.09.2024 hard 2024 kotlin rust

k lexicographically smallest value from 1..n

440. K-th Smallest in Lexicographical Order hard blog post substack youtube 1.webp

Join me on Telegram

https://t.me/leetcode_daily_unstoppable/743

Problem TLDR

k lexicographically smallest value from 1..n #hard #math

Intuition

If we try the solution from the previous day https://t.me/leetcode_daily_unstoppable/742 it will give us TLE as the problem size is too big 10^9. However, for Kotlin, the naive optimization of batch increments will pass:


val diff = min(nl, x + (10L - (x % 10L))) - x
if (i < k - diff) { x += diff; i += diff.toInt() }

The actual solution is to skip all numbers x0..x9, x00..x99, x000..x999, x0000..x9999, xx00000..xx99999 for every prefix x while they are less than target n.

Approach

  • steal someone else’s solution

Complexity

  • Time complexity: \(O(lg(k) * lg(n))\)

  • Space complexity: \(O(1)\)

Code


    fun findKthNumber(n: Int, k: Int): Int {
        var x = 1L; var i = 1; val nl = n.toLong()
        while (i < k) {
            if (x * 10L <= nl) x *= 10L else {
                if (x + 1L > nl) x /= 10L
                x++
                val diff = min(nl, x + (10L - (x % 10L))) - x
                if (i < k - diff) { x += diff; i += diff.toInt() }
                while (x > 0L && x % 10L == 0L) x /= 10L
            }
            i++
        }
        return x.toInt()
    }


    pub fn find_kth_number(n: i32, k: i32) -> i32 {
        let (mut x, mut i, n, k) = (1, 1, n as i64, k as i64);
        while i < k {
            let (mut count, mut from, mut to) = (0, x, x);
            while from <= n {
                count += to.min(n) - from + 1;
                from *= 10; to = to * 10 + 9
            }
            if i + count <= k { i += count; x += 1 }
            else { i += 1; x *= 10 }
        }
        x as i32
    }


    int findKthNumber(int n, int k) {
        long long x = 1, i = 1;
        while (i < k) {
            long long count = 0, from = x, to = x;
            while (from <= n) {
                count += min(to, static_cast<long long>(n)) - from + 1;
                from *= 10; to = to * 10 + 9;
            }
            if (i + count <= k) { i += count; x += 1; }
            else { i += 1; x *= 10; }
        }
        return static_cast<int>(x);
    }