问题描述
小U在研究一棵无限的二叉树,这棵树具有特殊的标记方式。每个节点都有两个子节点,并且树中的节点逐行依次按“之”字形进行标记:
- 在奇数行(例如,第1行、第3行、第5行……),节点按照从左到右的顺序进行标记。
- 在偶数行(例如,第2行、第4行、第6行……),节点按照从右到左的顺序进行标记。
1
/ \
3 2
/ \ / \
4 5 6 7
给定树上某个节点的标号 label,你的任务是返回从根节点到标号为 label 的节点的路径。路径中的节点依次为经过的节点标号。
测试样例
样例1:
输入:
label = 14
输出:[1, 3, 4, 14]
样例2:
输入:
label = 26
输出:[1, 2, 6, 10, 26]
样例3:
输入:
label = 1
输出:[1]
题目理解
这道题考察了一个特殊的无限二叉树:
- 每一层节点按“之”字形标记。
- 奇数行(例如第 1 行、第 3 行……)从左到右标记。
- 偶数行(例如第 2 行、第 4 行……)从右到左标记。
- 给定一个节点的标号
label,要求输出从根节点到该节点的路径。
例如:
- 输入
label = 14,输出[1, 3, 4, 14] - 输入
label = 26,输出[1, 2, 6, 10, 26]
解题思路
-
反向推导路径:
- 从给定的
label开始,逐步找到其父节点,直到根节点。 - 在二叉树中,任何节点的父节点可以通过数学公式推导出来。
- 从给定的
-
“之”字形的影响:
- 对于偶数层节点,节点标号的排列是反转的。需要根据当前层的开始和结束编号对标号进行修正,恢复其在正常二叉树中的父节点。
-
路径调整:
- 从目标节点
label回溯到根节点,得到的路径是从叶节点到根节点的,因此需要反转路径。
- 从目标节点
解决方案
以下是 Python 的实现:
def solution(label: int) -> list:
path = []
current = label
while current >= 1:
path.append(current)
row = current.bit_length() # 当前节点所在的行
start = 2 ** (row - 1) # 当前行起点
end = 2 ** row - 1 # 当前行终点
# 计算父节点编号
parent = (start + end - current) // 2
current = parent
return path[::-1] # 反转路径
案例分析
-
例子 1:
label = 14- 14 在第 4 行,起止范围为 [8, 15],父节点是 4。
- 4 在第 3 行,起止范围为 [4, 7],父节点是 3。
- 3 在第 2 行,起止范围为 [2, 3],父节点是 1。
- 根节点是 1。
- 路径为
[1, 3, 4, 14]。
-
例子 2:
label = 26- 26 在第 5 行,起止范围为 [16, 31],父节点是 10。
- 10 在第 4 行,起止范围为 [8, 15],父节点是 6。
- 6 在第 3 行,起止范围为 [4, 7],父节点是 2。
- 2 在第 2 行,起止范围为 [2, 3],父节点是 1。
- 路径为
[1, 2, 6, 10, 26]。
代码复杂度
-
时间复杂度:
- 主要在于计算路径的长度,取决于树的高度
- 时间复杂度为 ( O(h) )。
-
空间复杂度:
- 结果路径的长度为 ( O(h) )。