LeetCode 199.二叉树的右视图
Algorithm
- 🎯 问题(原题)
- 🛠️ 解题思路(结论概述)
- 📚 伪代码(右优先 DFS,递归)
- 🧾 C++ 实现(右优先 DFS,递归)
- 🧠 正确性说明(为什么能得到“右侧视图”)
- ⏱️ 时间复杂度分析
- 📦 空间复杂度分析
- 🔍 其他实现(层序遍历 BFS — 备选)
- ✅ 总结(要点)
🎯 问题(原题)
给定一个二叉树的根节点 root
,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
🛠️ 解题思路(结论概述)
-
🎯 目标:返回每一层从右侧能看到的第一个节点值(从上到下)。
-
✅ 最优时间复杂度:O(n)(必须访问每个结点至少一次)。
-
⚙️ 空间复杂度(最佳选择):
- 推荐做法(先右子树的深度优先搜索)使用递归或显式栈:O(h),
h
为树高(递归栈深度)。这是在平衡树上比宽度优先(BFS)更省空间的方案。 - 宽度优先(BFS/层序遍历)会使用队列,最坏情况空间 O(n)(当最宽层包含 O(n) 节点时)。
- 推荐做法(先右子树的深度优先搜索)使用递归或显式栈:O(h),
-
🧭 方案选择:优先采用 右优先的 DFS(深度优先) —— 访问顺序为:当前 → 右 → 左。对每个深度只记录第一次访问到的节点值(即从右侧看到的节点)。该方法能保证时间 O(n),空间 O(h)。
📚 伪代码(右优先 DFS,递归)
function rightSideView(root):result = empty listdfs(node=root, depth=0, result)return resultfunction dfs(node, depth, result):if node is null:returnif depth == length(result):append node.val to result // first node seen at this depth (right-most)dfs(node.right, depth + 1, result)dfs(node.left, depth + 1, result)
🧾 C++ 实现(右优先 DFS,递归)
#include <vector>
using namespace std;struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x): val(x), left(nullptr), right(nullptr) {}
};class Solution {
public:vector<int> rightSideView(TreeNode* root) {vector<int> result;dfs(root, 0, result);return result;}private:void dfs(TreeNode* node, int depth, vector<int>& result) {if (!node) return;// If this is the first time we reach this depth, node is the rightmost for this depthif (depth == (int)result.size()) {result.push_back(node->val);}// Visit right first so the first node encountered at each depth is the rightmostdfs(node->right, depth + 1, result);dfs(node->left, depth + 1, result);}
};
🧠 正确性说明(为什么能得到“右侧视图”)
- 在 DFS 中我们 先访问右子树,因此在每一层(depth)第一次被访问到的节点必然是该层最靠右的节点。我们用
depth == result.size()
判断该层是否已记录过节点:如果没记录(等于当前result长度),则当前节点是该深度的第一个(也即右侧看到的节点),把它加入结果。之后对左子树的访问不会覆盖该深度的记录。
⏱️ 时间复杂度分析
- 每个节点最多被访问一次(入 dfs 并返回),因此时间复杂度为 O(n),其中
n
是节点总数。 - 额外的开销为常数操作(比较、push 等),都被吞并进 O(n)。
📦 空间复杂度分析
-
递归栈深度取决于树的高度
h
:- 最优/平均(平衡树)情况下:
h = O(log n)
→ 空间 O(log n)(递归栈 + 结果数组)。 - 最坏情况(退化为链表):
h = O(n)
→ 空间 O(n)。
- 最优/平均(平衡树)情况下:
-
结果数组存储每层的一个节点:大小为层数,最坏为
O(n)
(当每层只有一个节点的链表情况),但通常视为与输出规模一致。 -
与 BFS(队列)相比:
- BFS 时间同为 O(n)。
- BFS 最坏空间是 O(n)(当某层很宽);而右优先 DFS 的空间是 O(h),在平衡树上明显优于 BFS。
🔍 其他实现(层序遍历 BFS — 备选)
- 思路:标准层序遍历(队列),每层遍历时记录该层最后被访问的节点值。
- 时间:O(n);空间:最坏 O(n)(队列)。
- 优点:直观;在某些场景(需要层信息)很方便。
- 缺点:在高度受限的场景,空间可能比 DFS 大。
✅ 总结(要点)
- 推荐实现:右优先 DFS(递归或显式栈),实现简单且一般能取得最优的辅助空间(O(h))。
- 时间复杂度必然是 O(n)。
- 空间复杂度是 O(h)(递归栈) + O(min(h, n))(输出数组),在平衡树上非常节省。