LeetCode 199.二叉树的右视图

Algorithm

  • [🎯 问题(原题)](#🎯 问题(原题))
    • [🛠️ 解题思路(结论概述)](#🛠️ 解题思路(结论概述))
    • [📚 伪代码(右优先 DFS,递归)](#📚 伪代码(右优先 DFS,递归))
    • [🧾 C++ 实现(右优先 DFS,递归)](#🧾 C++ 实现(右优先 DFS,递归))
    • [🧠 正确性说明(为什么能得到"右侧视图")](#🧠 正确性说明(为什么能得到“右侧视图”))
    • [⏱️ 时间复杂度分析](#⏱️ 时间复杂度分析)
    • [📦 空间复杂度分析](#📦 空间复杂度分析)
    • [🔍 其他实现(层序遍历 BFS --- 备选)](#🔍 其他实现(层序遍历 BFS — 备选))
    • [✅ 总结(要点)](#✅ 总结(要点))

🎯 问题(原题)

给定一个二叉树的根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。


🛠️ 解题思路(结论概述)

  • 🎯 目标:返回每一层从右侧能看到的第一个节点值(从上到下)。

  • ✅ 最优时间复杂度:O(n)(必须访问每个结点至少一次)。

  • ⚙️ 空间复杂度(最佳选择):

    • 推荐做法(先右子树的深度优先搜索)使用递归或显式栈:O(h)h 为树高(递归栈深度)。这是在平衡树上比宽度优先(BFS)更省空间的方案。
    • 宽度优先(BFS/层序遍历)会使用队列,最坏情况空间 O(n)(当最宽层包含 O(n) 节点时)。
  • 🧭 方案选择:优先采用 右优先的 DFS(深度优先) ------ 访问顺序为:当前 → 右 → 左。对每个深度只记录第一次访问到的节点值(即从右侧看到的节点)。该方法能保证时间 O(n),空间 O(h)。


📚 伪代码(右优先 DFS,递归)

plaintext 复制代码
function rightSideView(root):
    result = empty list
    dfs(node=root, depth=0, result)
    return result

function dfs(node, depth, result):
    if node is null:
        return
    if 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,递归)

cpp 复制代码
#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 depth
        if (depth == (int)result.size()) {
            result.push_back(node->val);
        }
        // Visit right first so the first node encountered at each depth is the rightmost
        dfs(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))(输出数组),在平衡树上非常节省。

相关推荐
10001hours3 小时前
C语言第23讲
c语言·开发语言·算法
h汉堡3 小时前
类和对象(二)
开发语言·数据结构·c++·学习
MoRanzhi12033 小时前
基于 SciPy 的矩阵运算与线性代数应用详解
人工智能·python·线性代数·算法·数学建模·矩阵·scipy
仰泳的熊猫3 小时前
LeetCode:239. 滑动窗口最大值
数据结构·c++·算法·leetcode
CoovallyAIHub3 小时前
版本号突袭!官方预览:YOLO26正式宣布,10月发布,CPU推理速度提升43%
深度学习·算法·计算机视觉
程序员学习随笔4 小时前
C++ 性能优化:用 CRTP 实现零开销编译期多态
java·c++
爱和冰阔落4 小时前
【C++list】底层结构、迭代器核心原理与常用接口实现全解析
开发语言·数据结构·c++·list
Ms.lan4 小时前
C++数组
数据结构·c++·算法·visual studio
~~李木子~~4 小时前
归并排序算法
数据结构·算法·排序算法