440. K-th Smallest in Lexicographical Order
Given two integers n and k, return the k t h k^{th} 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 < = 1 0 9 1 <= k <= n <= 10^9 1<=k<=n<=109
From: LeetCode
Link: 440. K-th Smallest in Lexicographical Order
Solution:
Ideas:
1. countPrefix Function:
- Counts how many numbers exist under the given prefix within the range [1, n].
- Expands the prefix by multiplying by 10 (curr *= 10) and keeps expanding until curr exceeds n.
- Adjusts for cases where there are fewer numbers than the full range in each depth level.
2. findKthNumber Function:
- Starts at current = 1 (first lexicographical number).
- Uses countPrefix to check if the k-th number lies within the subtree rooted at current.
- If count is less than k, we move to the next sibling (current++) and reduce k by count.
- If count is greater than k, we move deeper into the tree (current *= 10) and decrement k by 1.
3. Return Result:
- When k reaches 0, current is the k-th lexicographical number.
Code:
int countPrefix(int prefix, long n) {
long curr = prefix;
long next = prefix + 1;
int count = 0;
while (curr <= n) {
count += (int)(next - curr < n - curr + 1 ? next - curr : n - curr + 1);
curr *= 10;
next *= 10;
}
return count;
}
int findKthNumber(int n, int k) {
int current = 1;
k--; // As we're starting with the first element '1'
while (k > 0) {
int count = countPrefix(current, n);
if (count <= k) {
// Move to next sibling
k -= count;
current++;
} else {
// Go deeper
current *= 10;
k--;
}
}
return current;
}