背景简介
在 LeetCode 的经典题目 「二叉树的右视图」 中,我们需要返回从右侧看一棵二叉树时所能看到的节点集合。每一层我们只能看到最右边的那个节点。
最初,我采用了一个常规思路:层序遍历 + 每层单独保存节点值 + 最后提取每层最后一个节点。但在逐步分析中,我发现这一过程可以进一步优化,减少中间变量的使用,提高代码简洁度和可读性。
初始版本思路(注释中的方式)
下面是我最初的设计思路片段:
while(!que.empty()){int size = que.size();vector<int> vec; // 用于存储当前层所有节点的值for(int i = 0; i < size; i++){TreeNode* node = que.front();que.pop();vec.push_back(node -> val); // 保存该节点值if(node -> left) que.push(node -> left);if(node -> right) que.push(node -> right);}res.push_back(vec[size - 1]); // 每层最后一个加入结果
}
✅ 优点:
- 清晰直观
- 完全符合“层序遍历 + 每层最后一个”这一概念
❌ 缺点:
- 使用了额外的
vector<int> vec
存储每层节点值,造成 冗余 - 实际我们并不需要保留整层的所有值,只关心最后一个
优化思路
我们只需要每层的最后一个节点值,那么在遍历这一层时,只需判断当前访问的是不是“最后一个节点”。如果是,就将其值加入结果集即可,无需保留整层节点值。
于是我们这样优化:
while(!que.empty()){int size = que.size();for(int i = 0; i < size; i++){TreeNode* node = que.front();que.pop();// 只记录这一层的最后一个节点if(i == size - 1) res.push_back(node -> val);if(node -> left) que.push(node -> left);if(node -> right) que.push(node -> right);}
}
最终代码(优化后)
class Solution {
public:vector<int> rightSideView(TreeNode* root) {vector<int> res;queue<TreeNode*> que;if(root) que.push(root);while(!que.empty()){int size = que.size();for(int i = 0; i < size; i++){TreeNode* node = que.front();que.pop();if(i == size - 1) res.push_back(node -> val);if(node -> left) que.push(node -> left);if(node -> right) que.push(node -> right);}}return res;}
};
总结感悟
这次的优化过程,让我意识到:
- 在写树的层序遍历时,可以根据最终需求精简逻辑,避免中间冗余变量;
if(i == size - 1)
是提取“最后一个节点”的一个技巧写法;- 小优化虽不影响时间复杂度,但能提升代码的风格统一性、清晰度和执行效率。
延伸思考
这种写法和风格也适用于以下类似题目:
- 二叉树的左视图(
i == 0
) - 每层最大值(可扩展为取每层最大而非最后一个)
- 分层打印(保留每层节点)
- 广度优先路径模拟(如迷宫路径、AI寻路)