440. K-th Smallest in Lexicographical Order
Description
Given two integers n and k, return the kth lexicographically smallest integer in the range [1, n].
Example 1:
Input: n = 13, k = 2 Output: 10 Explanation: The lexicographical order is [1, 10, 11, 12, 13, 2, 3, 4, 5, 6, 7, 8, 9], so the second smallest number is 10.
Example 2:
Input: n = 1, k = 1 Output: 1
Constraints:
1 <= k <= n <= 109
Solutions
Solution 1: Trie-Based Counting + Greedy Construction
Thinking
\(n\) can be \(10^9\), so we cannot list and sort. Lexicographic order is a \(10\)-ary trie: the children of \(x\) are \(10x,\ldots,10x+9\) that stay \(\le n\).
Count the subtree of a prefix \(curr\) by intersecting \([curr,curr+1)\) with \([1,n]\) at each extra digit. If that count is \(\le k\), skip the whole tree and increment \(curr\); otherwise step into \(curr\times 10\) and spend one for the prefix itself.
Decrement \(k\) once at the start because we already stand on \(1\). Layered counting never enumerates every integer in the subtree.
The problem asks for the $k$-th smallest number in the range \([1, n]\) when all numbers are sorted in lexicographical order. Since \(n\) can be as large as \(10^9\), we cannot afford to generate and sort all the numbers explicitly. Instead, we adopt a strategy based on greedy traversal over a conceptual Trie.
We treat the range \([1, n]\) as a 10-ary prefix tree (Trie):
- Each node represents a numeric prefix, starting from an empty root;
- Each node has 10 children, corresponding to appending digits \(0 \sim 9\);
- For example, prefix \(1\) has children \(10, 11, \ldots, 19\), and node \(10\) has children \(100, 101, \ldots, 109\);
- This tree naturally reflects lexicographical order traversal.
root
├── 1
│ ├── 10
│ ├── 11
│ ├── ...
├── 2
├── ...
We use a variable \(\textit{curr}\) to denote the current prefix, initialized as \(1\). At each step, we try to expand or skip prefixes until we find the $k$-th smallest number.
At each step, we calculate how many valid numbers (i.e., numbers \(\le n\) with prefix \(\textit{curr}\)) exist under this prefix subtree. Let this count be \(\textit{count}(\text{curr})\):
-
If \(k \ge \text{count}(\text{curr})\): the target number is not in this subtree. We skip the entire subtree by moving to the next sibling:
\[ \textit{curr} \leftarrow \textit{curr} + 1,\quad k \leftarrow k - \text{count}(\text{curr}) \] -
Otherwise: the target is within this subtree. We go one level deeper:
\[ \textit{curr} \leftarrow \textit{curr} \times 10,\quad k \leftarrow k - 1 \]
At each level, we enlarge the current range by multiplying by 10 and continue descending until we exceed \(n\).
The time complexity is \(O(\log^2 n)\), as we perform logarithmic operations for counting and traversing the Trie structure. The space complexity is \(O(1)\) since we only use a few variables to track the current prefix and count.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |