题目描述

✅ LCR 046. 二叉树的右视图

image-20260929005048693

image-20260929005048695

题意分析

右视图由每一层最右侧节点的值组成,按深度从上到下返回。这个节点可能来自左子树,只沿右孩子一直向下并不能得到完整答案;空树返回空列表。

解法:BFS 先右后左遍历

核心思路

[!blue]

用 BFS 逐层处理,并让同层节点在队列中按从右到左排列。这样每轮开始时,队首就是本层最右节点,直接记录它的值即可,不必保存这一层的全部值。

根节点单独成层,显然满足这个顺序。处理一层时,父节点已经从右到左出队,再对每个父节点先加入右孩子、后加入左孩子,就会让下一层同样从右到左排列。缺少某个孩子只会少加入一个节点,不会改变其余节点的相对顺序。

每轮必须先固定当前队列长度,只消费这些节点。遍历中追加的是下一层节点,不能把它们继续算进本层。消费完固定数量后,队列恰好变成下一层,层序和队首取值的依据就能一直保持。

解题步骤

  • 根节点为空时直接返回空列表,否则将根节点入队。
  • 每轮读取队首节点的值加入答案,先不将它弹出,它仍需参与本层的孩子扩展。
  • 记录本层节点数,并恰好出队这么多个节点;每次先加入非空右孩子,再加入非空左孩子。
  • 队列为空时所有层都已处理,返回答案。

一层只有一个节点时,它自然就是队首;右子树没有更深节点时,左子树剩余节点仍会进入后续层。因此每层恰好贡献一个值,答案长度等于树高。

代码实现

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> answer = new ArrayList<>();

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

        Deque<TreeNode> q = new ArrayDeque<>();

        q.offer(root);

        while (!q.isEmpty()) {
            answer.add(q.peekFirst().val);

            for (int i = q.size(); i > 0; --i) {
                TreeNode node = q.poll();

                if (node.right != null) {
                    q.offer(node.right);
                }

                if (node.left != null) {
                    q.offer(node.left);
                }
            }
        }

        return answer;
    }
}
func rightSideView(root *TreeNode) []int {
    var answer []int
    if root == nil {
        return answer
    }
    q := []*TreeNode{
        root,
    }
    for len(q) > 0 {
        answer = append(answer, q[0].Val)
        for i := len(q); i > 0; i-- {
            node := q[0]
            q = q[1:]
            if node.Right != nil {
                q = append(q, node.Right)
            }
            if node.Left != nil {
                q = append(q, node.Left)
            }
        }
    }
    return answer
}

复杂度分析

  • 时间复杂度:$O(n)$,每个节点恰好入队和出队一次,每层只额外读取一次队首。
  • 空间复杂度:不计答案为 $O(w)$,$w$ 为最大层宽,队列同时容纳相邻两层的部分节点;答案占 $O(h)$,$h$ 为树高。

关键点总结

[!green]

  • 先右后左入队和每层取队首需要配合使用。
  • 固定本层节点数,才能把本层处理与下一层入队分开。
  • 所有节点都要正常扩展,只有记录答案时每层选一个。

易错点总结

[!yellow]

  • 当前实现先右后左入队,每层队首才是最右节点;改入队方向就要同步改取值规则。
  • 读队首时使用 peek,不提前弹走尚未扩展孩子的节点。
  • 空树返回空列表,一层只记录一个值,不能只沿原树右孩子走到底。

相似题目

题目 难度 关联与区别
515. 在每个树行中找最大值 中等 同样每层输出一个值,但最大值与最右节点无关,不能混淆选择条件。
513. 找树左下角的值 中等 同样取层的边界节点,原题只保留最深层最左值,本题保留每层最右值。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/21997854
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!