K-th Smallest in Lexicographical Order

hard trie math

Problem

Given integers n and k, return the k-th lexicographically smallest integer in [1, n]. Treat numbers as strings: "1" < "10" < "100" < "2".

Inputn = 13, k = 2
Output10
Lex order: 1, 10, 11, 12, 13, 2, 3, …; the 2nd is 10.

def find_kth_number(n, k):
    def steps(prefix):
        # numbers in [prefix, prefix+1) prefix-tree, capped by n
        first, last, cnt = prefix, prefix, 0
        while first <= n:
            cnt += min(n, last) - first + 1
            first *= 10
            last = last * 10 + 9
        return cnt

    cur, k = 1, k - 1
    while k > 0:
        s = steps(cur)
        if s <= k:
            k -= s
            cur += 1
        else:
            k -= 1
            cur *= 10
    return cur
function findKthNumber(n, k) {
  function steps(prefix) {
    let first = prefix, last = prefix, cnt = 0;
    while (first <= n) {
      cnt += Math.min(n, last) - first + 1;
      first *= 10;
      last = last * 10 + 9;
    }
    return cnt;
  }
  let cur = 1; k -= 1;
  while (k > 0) {
    const s = steps(cur);
    if (s <= k) { k -= s; cur += 1; }
    else { k -= 1; cur *= 10; }
  }
  return cur;
}
class Solution {
    long steps(long prefix, int n) {
        long first = prefix, last = prefix, cnt = 0;
        while (first <= n) {
            cnt += Math.min((long) n, last) - first + 1;
            first *= 10;
            last = last * 10 + 9;
        }
        return cnt;
    }
    public int findKthNumber(int n, int k) {
        long cur = 1; k -= 1;
        while (k > 0) {
            long s = steps(cur, n);
            if (s <= k) { k -= s; cur += 1; }
            else { k -= 1; cur *= 10; }
        }
        return (int) cur;
    }
}
long long stepsHelper(long long prefix, int n) {
    long long first = prefix, last = prefix, cnt = 0;
    while (first <= n) {
        cnt += min((long long) n, last) - first + 1;
        first *= 10;
        last = last * 10 + 9;
    }
    return cnt;
}
int findKthNumber(int n, int k) {
    long long cur = 1; k -= 1;
    while (k > 0) {
        long long s = stepsHelper(cur, n);
        if (s <= k) { k -= s; cur += 1; }
        else { k -= 1; cur *= 10; }
    }
    return (int) cur;
}
Time: O(log² n) Space: O(1)