二叉树之字形标记路径 | 豆包MarsCode AI刷题

115 阅读3分钟

问题描述

小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. 每一层节点按“之”字形标记。
    • 奇数行(例如第 1 行、第 3 行……)从左到右标记。
    • 偶数行(例如第 2 行、第 4 行……)从右到左标记。
  2. 给定一个节点的标号 label,要求输出从根节点到该节点的路径。

例如:

  • 输入 label = 14,输出 [1, 3, 4, 14]
  • 输入 label = 26,输出 [1, 2, 6, 10, 26]

解题思路

  1. 反向推导路径

    • 从给定的 label 开始,逐步找到其父节点,直到根节点。
    • 在二叉树中,任何节点的父节点可以通过数学公式推导出来。
  2. “之”字形的影响

    • 对于偶数层节点,节点标号的排列是反转的。需要根据当前层的开始和结束编号对标号进行修正,恢复其在正常二叉树中的父节点。
  3. 路径调整

    • 从目标节点 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. 例子 1label = 14

    • 14 在第 4 行,起止范围为 [8, 15],父节点是 4。
    • 4 在第 3 行,起止范围为 [4, 7],父节点是 3。
    • 3 在第 2 行,起止范围为 [2, 3],父节点是 1。
    • 根节点是 1。
    • 路径为 [1, 3, 4, 14]
  2. 例子 2label = 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]

代码复杂度

  1. 时间复杂度

    • 主要在于计算路径的长度,取决于树的高度
    • 时间复杂度为 ( O(h) )。
  2. 空间复杂度

    • 结果路径的长度为 ( O(h) )。