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在树结构中的应用
  • 如何处理二叉树层级信息
  • 每层节点的统计技巧
相关推荐
清泓y5 小时前
RAG 技术
算法·ai
阿慧今天瘦了嘛5 小时前
计算机组成原理概述:从硬件到软件的桥梁
计算机网络·算法
网站优化(SEO)专家6 小时前
SEO核心算法拆解:网站排名快速提升的武林秘籍!
算法·搜索引擎·网站排名·核心算法
惊讶的猫6 小时前
CLGSI
人工智能·算法·机器学习
ysa0510307 小时前
【板子】二分答案(最大最小?)
c++·笔记·算法·板子
科技之门7 小时前
百公里管网漏损分级定位实战方案2026
前端·人工智能·算法
木木子227 小时前
# 猜数字游戏 — HarmonyOS交互逻辑与随机算法实现
算法·游戏·华为·交互·harmonyos
stolentime8 小时前
SP8549 MAIN75 - BST again题解
c++·算法·二叉树·深度优先·图论·记忆化搜索·组合数学
stolentime8 小时前
AT_pakencamp_2020_day1_k Gcd of Sum题解
c++·算法
2601_956121978 小时前
map_计蒜客T1271 完美K倍子数组
c++·算法