LeetCode 199:二叉树的右视图 —— 利用层序遍历获取每层最右节点

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

示例:

输入:

复制代码
root = [1,2,3,null,5,null,4]

对应二叉树:

复制代码
        1
       / \
      2   3
       \   \
        5   4

从右侧观察:

复制代码
1
3
4

输出:

复制代码
[1,3,4]

另一个例子:

输入:

复制代码
root = [1,null,3]

结构:

复制代码
    1
     \
      3

输出:

复制代码
[1,3]

二、为什么这道题值得学习?

这道题是二叉树遍历中的经典问题,也是面试高频题。

它主要考察:

  • 二叉树层序遍历
  • BFS 广度优先搜索
  • 如何获取每一层指定位置的节点

很多同学看到"右视图"可能会想到:

从右边一直遍历。

但实际上:

二叉树右视图的本质是:

每一层中最右边的节点。

例如:

复制代码
        1
       / \
      2   3
     /     \
    4       5

按照层序遍历:

第一层:

复制代码
1

第二层:

复制代码
2 3

第三层:

复制代码
4 5

右视图看到的就是:

复制代码
1 3 5

所以:

只需要找到每一层最后访问的节点即可。


三、核心思想:层序遍历 + 记录每层最后一个节点

二叉树层序遍历:

也就是 BFS。

遍历顺序:

复制代码
从上到下
从左到右

例如:

复制代码
        1
       / \
      2   3
     / \
    4   5

访问顺序:

复制代码
1
2 3
4 5

如果我们知道:

当前层有多少个节点。

那么:

这一层最后被访问的节点:

就是右视图看到的节点。

所以算法步骤:

  1. 使用队列保存节点
  2. 每次处理一层节点
  3. 记录当前层最后一个节点
  4. 加入结果数组

四、解题思路分析

1. 使用队列进行层序遍历

首先定义队列:

复制代码
Queue<TreeNode>

用于保存当前需要访问的节点。

初始化:

将根节点加入队列。


2. 获取当前层节点数量

每次进入循环:

记录当前层节点数量:

复制代码
int size = queue.size();

例如:

当前队列:

复制代码
[2,3]

说明:

这一层有两个节点。


3. 判断是否为当前层最后一个节点

遍历当前层:

复制代码
for(int i = 0; i < size; i++)

当:

复制代码
i == size - 1

说明:

当前节点是这一层最后访问的节点。

也就是:

右视图看到的节点。

加入答案:

复制代码
result.add(node.val);

五、代码实现(BFS层序遍历)

复制代码
class Solution {

    public List<Integer> rightSideView(TreeNode root) {

        List<Integer> result = new ArrayList<>();

        if(root == null){
            return result;
        }


        Queue<TreeNode> queue = new LinkedList<>();

        queue.offer(root);


        while(!queue.isEmpty()){


            // 当前层节点数量
            int size = queue.size();


            for(int i = 0; i < size; i++){

                TreeNode node = queue.poll();


                // 当前层最后一个节点
                if(i == size - 1){
                    result.add(node.val);
                }


                // 左节点加入队列
                if(node.left != null){
                    queue.offer(node.left);
                }


                // 右节点加入队列
                if(node.right != null){
                    queue.offer(node.right);
                }

            }
        }


        return result;
    }
}

六、过程图解

例如:

复制代码
        1
       / \
      2   3
       \   \
        5   4

要求:

复制代码
右视图

第一层

队列:

复制代码
[1]

数量:

复制代码
size = 1

访问:

复制代码
1

因为:

复制代码
i = size - 1

所以加入:

复制代码
result = [1]

加入下一层:

复制代码
[2,3]

第二层

队列:

复制代码
[2,3]

数量:

复制代码
size = 2

访问:

节点2:

复制代码
i = 0

不是最后一个。

访问:

节点3:

复制代码
i = 1

满足:

复制代码
i == size - 1

加入:

复制代码
result = [1,3]

第三层

队列:

复制代码
[5,4]

访问:

节点5:

不是最后。

访问:

节点4:

最后一个节点。

加入:

复制代码
result = [1,3,4]

最终答案:

复制代码
[1,3,4]

七、复杂度分析

时间复杂度:

复制代码
O(N)

原因:

每个节点都会被访问一次。


空间复杂度:

复制代码
O(N)

原因:

队列最多存储一层节点。

在最坏情况下:

完全二叉树最后一层节点数量接近:

复制代码
N/2

所以空间复杂度为:

复制代码
O(N)

八、另一种方法:DFS递归

除了 BFS。

也可以使用深度优先遍历。

核心思想:

优先访问右子树。

因为:

右边节点更可能出现在右视图中。

遍历顺序:

复制代码
根节点
 ↓
右子树
 ↓
左子树

例如:

复制代码
        1
       / \
      2   3
          \
           4

访问:

复制代码
1
3
4
2

每个深度第一次访问到的节点:

就是该层右侧节点。

代码:

复制代码
class Solution {

    List<Integer> result = new ArrayList<>();


    public List<Integer> rightSideView(TreeNode root) {

        dfs(root,0);

        return result;
    }


    private void dfs(TreeNode root,int depth){

        if(root == null){
            return;
        }


        // 当前深度第一次访问
        if(depth == result.size()){
            result.add(root.val);
        }


        // 优先遍历右子树
        dfs(root.right,depth + 1);


        // 再遍历左子树
        dfs(root.left,depth + 1);
    }
}

九、两种方法比较

方法 思路 时间复杂度 空间复杂度
BFS 每层记录最后节点 O(N) O(N)
DFS 优先访问右节点 O(N) O(H)

面试中:

更加推荐:

✅ BFS层序遍历

因为它更加符合"右视图"的定义。


十、常见错误与避坑指南

❌ 错误一:只遍历右子树

很多人认为:

右视图就是一直走右孩子。

这是错误的。

例如:

复制代码
        1
       /
      2
       \
        3

如果只走右边:

只能得到:

复制代码
1

但是实际右视图:

复制代码
1
2
3

原因:

右视图看的是:

每层最右节点。

不是:

整棵树的右链。


❌ 错误二:记录每层第一个节点

错误:

复制代码
i == 0

这样得到的是:

左视图。

右视图应该:

记录:

复制代码
i == size - 1

❌ 错误三:忽略空树情况

如果:

复制代码
root = null

应该返回:

复制代码
[]

所以需要提前判断:

复制代码
if(root == null)

十一、面试高频追问

1. 为什么 BFS 可以解决右视图?

因为:

BFS 按层遍历。

而右视图要求:

每层最右节点。

所以:

记录每层最后访问节点即可。


2. 为什么 DFS 要先访问右子树?

因为:

右子树节点优先被访问。

每个深度第一次出现的节点:

就是该层最右节点。


3. 如果要求左视图怎么办?

只需要改变遍历顺序:

左视图:

记录每层第一个节点。

DFS:

优先访问左子树。


总结

LeetCode 199 的核心思想是:

二叉树右视图 = 每一层最右侧节点。

通过:

复制代码
层序遍历 BFS

控制每层节点数量:

复制代码
遍历当前层
      ↓
记录最后一个节点
      ↓
加入答案

这道题不仅考察二叉树遍历,

还帮助理解:

  • BFS在树结构中的应用
  • 如何处理二叉树层级信息
  • 每层节点的统计技巧
相关推荐
笨笨饿8 分钟前
#111_关于FreeRTOS面试的一些题目
linux·ubuntu·面试·职场和发展·centos·rtos
星星.72222 分钟前
C++算法竞赛|二分查找与二分答案:边界模板、浮点二分、STL
数据结构·c++·算法
sel_924 分钟前
【OPD论文导读(二)】OPD(On-Policy Distillation)全景调研:十篇论文讲透“在自己生成的内容上学习“这件事
人工智能·python·深度学习·学习·算法·语言模型
金幄科技1 小时前
RAG第四篇:重排序 Rerank——粗召回之后,为什么还需要一次精排
人工智能·算法·ai·ai编程
M78佐菲1 小时前
Linux学习笔记:文件IO
linux·笔记·学习·算法
lhldsg2 小时前
课程排课系统实战指南:从数据库设计到算法调优全流程解析
java·数据库·算法·小程序
BSD_HY2 小时前
薄膜开关矩阵扫描电路设计中的防鬼键措施
人工智能·算法·矩阵·人机交互·薄膜开关·源头工厂·深圳工厂
linux-hzh2 小时前
百日算法修炼 · Day 17
数据结构·算法
XUEYUAN52122 小时前
代理日志分析与监控:代理池健康状态巡检与分级告警体系搭建(运维实战)
运维·网络·网络协议·tcp/ip·算法·架构
sel_92 小时前
【多轮对话论文导读(七)】多轮对话论文阅读笔记:从数据生成、用户模拟到上下文重构与长期记忆
论文阅读·人工智能·笔记·深度学习·算法·语言模型·自然语言处理