青训营笔记4 | 豆包MarsCode AI刷题

84 阅读4分钟

题目

二叉树之字形标记路径

小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]

题目分析

  题目要求在一个无限的二叉树中,找到从根节点到给定节点 label 的路径。这棵二叉树的节点按照“之”字形进行标记,即奇数层从左到右标记,偶数层从右到左标记。我们需要找到从根节点到指定节点的路径,并返回路径上的所有节点标号。

  • 关键点
  1. 确定节点所在的层数:通过 log2(label) 计算节点所在的层数 level
  2. 逆向寻找路径:从给定的 label 开始,不断向上回溯到根节点。需要注意的是,由于“之”字形的标记方式,需要根据节点所在层是否为偶数来调整计算父节点的方法。
  3. 记录路径:每找到一个父节点,将其添加到路径列表中,直到达到根节点。
  4. 反转路径:因为是从下往上找的,所以最后需要将路径反转,使其从根节点开始

解题步骤

  1. 初始化路径列表:创建一个空列表 result 用于存储路径。

  2. 循环回溯父节点

    • 使用 while 循环,条件是 label 不等于 1
    • 计算当前节点所在的层数 level
    • 根据层数的奇偶性,计算当前节点在标准情况下的值 standard_label
    • 计算父节点的标准值 parent_label
    • 根据父节点所在的层数,决定是否需要转换回“之”字形的值。
    • 更新 label 为父节点的值,并将其添加到路径列表中。
  3. 添加根节点:将根节点 1 添加到路径列表中。

  4. 反转路径:将路径列表反转,使其从根节点开始。

代码实现

import math

def solution(label):
    result = []
    while label != 1:
        result.append(label)
        # 当前节点所在层数
        level = int(math.log2(label))  
        
        # 计算 label 在标准情况下的值
        if level % 2 == 0:  # 偶数层
            standard_label = label
        else:  # 奇数层
            standard_label = (2**level + 2**(level + 1) - 1 - label)
        
        # 计算父节点的值
        parent_label = (standard_label // 2)
        
        # 如果父节点在偶数层,需要转换回“之”字形的值
        if (level - 1) % 2 == 0:  # 父节点在偶数层
            label = parent_label
        else:  # 父节点在奇数层
            label = (2**(level - 1) + 2**level - 1 - parent_label)
    
    result.append(1)  # 添加根节点
    return result[::-1]  # 反转列表,使路径从根节点开始

复杂度分析

时间复杂度

  1. 计算层数:每次计算当前节点所在的层数 level 需要使用 math.log2(label),这是一个常数时间操作O(1)O(1)
  2. 回溯父节点:从给定的 label 节点回溯到根节点 1。每次回溯一步,label 的值会减少大约一半。因此,回溯的次数与 label 的二进制位数成正比,即 O(loglabel)O(log label)

空间复杂度

  1. 路径列表:用列表来存储从根节点到给定节点 label 的路径。最坏情况下,路径长度为 log2labellog_2label,因为这是从根节点到任意节点的最大路径长度。
  2. 其他变量:除了路径列表外,还要用一些额外的变量存储当前节点的层数、标准位置等信息。这些变量占用的空间是常数级别的O(1)O(1)

总结

  主要是根据label找到该节点对应的层,以及根据根据某个节点找到它的父节点的label,一直往上找,直到根节点,最后反转。