“青训营X豆包MarsCode 实践记录AI助力 二叉树之字形标记路径 | 豆包MarsCode AI 刷题”

84 阅读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]

知识回顾

对于 完全二叉树 或者按层序遍历的二叉树来说,父子节点之间的关系有一种非常简单的数学公式。

假设当前节点编号为 i

  • 父节点的编号是 i // 2
  • 左子节点的编号是 2 * i
  • 右子节点的编号是 2 * i + 1

题目分析与思考

首先,计算出label对应的层数,设1所在的层为0层。

每层元素的数目为2*i 即第0层有1个元素、第1层有2个元素、第2层有4个元素,依次类推

计算出label所在的层数后,要注意。我们设定的层数和题目设定的刚好是反的。

例如:4 5 6 7 这一层,我们的设定是第二层,题目是第三层,所以左右刚好相反。

确定了层数之后,就要开始回溯了。

首先将lable加入最终结果列表。之后lable这个变量是会发生变化的,回溯过程中每层的元素是哪个lable就设定为哪个元素。以便继续向上回溯元素。

计算出每层最小的元素和最大的元素,最小的元素设定为start,最大的元素设定为end.

开始循环,每次循环结束后,层数level-1,其实循环条件可以设定为level>0,但是设定为label > 1也有同样的效果

如果level是奇数,那么他这一层其实是反向放置数字的,所以要先找到这一行的元素原来对应的位置,也就是做一个对称:label = end - (label - start)。做完对称之后,在利用父节点与子节点的关系,寻找该元素的父节点,也就是label = label // 2。

如果level是偶数,那么他这一层的元素是正向放置的,他上一层的元素是反向放置的,所以先找到上一层元素对应的位置:label //= 2。然后找到上一层元素的最小和最大值: start = 2 ** (level-1)以及end = (2 ** level) - 1,之后将上一层的元素进行对称label = end - (label - start),即可找到上一层的元素。

在每层找到元素之后,将其添加进结果列表: path.append(label)

最后反向输出结果列表即可:return path[::-1]

image.png

image.png

其实在做题的时候不仅可以借助AI助手查询自己不确定的知识点,同时也可以利用AI对不编程过程中的部分函数进行单元测试,例如上题中就可以检查part1元素层数的判断是否正确,然后尽兴part2的编码。