假设要找到第12小的字典序数(101)
解题要点:
(1) 数字为i的前缀一定比数字为i+1的前缀小,位置靠前。
1 | 2 | … | 9 |
---|---|---|---|
10,11,12,13,14,15,16,17,18,19 | 20,21,22,23,24,25,26,27,28,29 | 90~99 | |
101,102,103 |
(2) 如何求得前缀为i的树有多少个结点?
针对每一层,下一个前缀减去当前前缀
- k位置的数在i 这个前缀树里时候 n+1 - prefix
- k位置的数不在这个i(例如,10)的前缀树里,那么查看最邻近的前缀树,比如i+1(11)
总结 从i前缀跨越到下一个前缀即i+1,需要min(next_prefix, n+1) - prefix
class Solution:
def findKthNumber(self, n: int, k: int) -> int:
# 同一层的两个节点间,移动需要的步数
def count_steps(prefix, next_prefix) -> int:
# 逐层累加步数
cnt = 0
while prefix <= n:
cnt += min(next_prefix, n+1) - prefix # 本层中有多少个结点。
prefix, next_prefix = prefix * 10, next_prefix * 10 # 去往下一层。
return cnt
#开始搜索,如图目标在当前前缀下,去往下一层
cur_val, idx = 1, 1
while True:
if idx == k:
return cur_val
steps = count_steps(cur_val, cur_val + 1) # 这个前缀下有多少个点
if idx + steps <= k:
idx += steps #去往下一个后缀,同层node
cur_val = cur_val + 1 # 去往同层下一个
else:
idx += 1 # 顺序枚举
cur_val = cur_val * 10 # 去往下一层