LeetCode 222中等二叉树
完全二叉树的节点个数 图解题解
这道题到底在问什么
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。 完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(从第 0 层开始),则该层包含 1~ 2 h 个节点。
- root
- [1,2,3,4,5,6]
- 输出
- 6
先想最直接的笨办法
二叉树状态跟着代码走:推进语句是:node = node.left。处理过的部分不再重新枚举。(动画第 10 步)
最优解:一步一步想明白
- 3下面 9 步动画会按主解代码推进,而不是泛泛讲题型。
- 4先读清 完全二叉树的节点个数 的输入输出二叉树状态跟着代码走:先把示例输入映射到代码参数:def countNodes(self, root):。
- 5初始化核心变量二叉树状态跟着代码走:开局只立住必要变量:root / node / left / right。
- 6while node:二叉树状态跟着代码走:主流程从这里开始:while node:。
- 7if not root:二叉树状态跟着代码走:题目条件落到这一行:if not root:。
- 8return (1 << lh) + self.countNodes(root.right)二叉树状态跟着代码走:对应代码:return (1 << lh) + self.countNodes(root.right)。这一行决定当前轮对答案有什么贡献。
- 9利用完全二叉树性质二叉树状态跟着代码走:边界跟着代码看:return (1 << rh) + self.countNodes(root.left)。
- 10node = node.left二叉树状态跟着代码走:推进语句是:node = node.left。处理过的部分不再重新枚举。
- 11return (1 << rh) + self.countNodes(root.left)二叉树状态跟着代码走:到这里,root 已经能表达题目要求。
- 12return:return (1 << rh) + self.countNodes(root.left)二叉树状态跟着代码走:最后检查返回形态:返回值、原地修改或设计类状态,要和 LeetCode 判题方式一致。
- 15记住这题的代码骨架:题意约束先落到状态变量,再用循环或递归维护它。
⚠️ 容易写错的地方
✗ 错:普通 DFS 计数
✓ 对:利用完全二叉树性质
题目希望更优复杂度
✗ 错:满子树节点数公式写错
✓ 对:高度 h 的满树有 2^h-1 个节点
这里高度按节点数计算
完整代码(Python)
Python
class Solution:
def countNodes(self, root):
def height(node):
h = 0
while node:
h += 1
node = node.left
return h
if not root:
return 0
lh = height(root.left)
rh = height(root.right)
if lh == rh:
return (1 << lh) + self.countNodes(root.right)
return (1 << rh) + self.countNodes(root.left)复杂度
时间复杂度
O(log^2 n)
每层计算高度
空间复杂度
O(log n)
递归栈
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 完全二叉树的节点个数 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
这道题为什么用「二叉树」,换最直接的暴力解会差在哪?+
二叉树抓住了本题的结构特征,把暴力解里重复的工作省掉;暴力解通常要多嵌套一层枚举,数据一大就超时。具体对比见上文「暴力解及其卡点」与「最优解逐步推演」两节。
时间复杂度为什么是 undefined?怎么推出来的?+
按上文复杂度小节的推导,时间复杂度为 undefined。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。