Skip to content

二叉树的右视图

约 713 字大约 2 分钟

2025-02-28

199. 二叉树的右视图

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

示例 1:

img.png

输入: [1,2,3,null,5,null,4]
输出: [1,3,4]

示例 2:

输入: [1,null,3]
输出: [1,3]

示例 3:

输入: []
输出: []

提示:

  • 二叉树的节点个数的范围是 [0,100]
  • -100 <= Node.val <= 100

103. 二叉树的锯齿形层序遍历

层序遍历

每一层头部就是最右侧的元素。

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> res = new LinkedList<>();
        if (root == null) {
            return res;
        }
        
        // BFS 层序遍历,计算右侧视图
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        
        // while 循环控制从上向下一层层遍历
        while (!q.isEmpty()) {
            int sz = q.size();
            
            // 每一层头部就是最右侧的元素
            TreeNode last = q.peek();
            for (int i = 0; i < sz; i++) {
                TreeNode cur = q.poll();
                // 控制每一层从右向左遍历
                if (cur.right != null) {
                    q.offer(cur.right);
                }
                if (cur.left != null) {
                    q.offer(cur.left);
                }
            }
            
            // 每一层的最后一个节点就是二叉树的右侧视图。这行代码也可以放在for上面。
            res.add(last.val);
        }
        return res;
    }
}
  • 时间复杂度 : O(n)。 每个节点最多进队列一次,出队列一次,因此广度优先搜索的复杂度为线性。
  • 空间复杂度 : O(n)。每个节点最多进队列一次,所以队列长度最大不不超过 (n+1)/2,所以这里的空间代价为 O(n)。

回溯,无返回值无信息参数DFS,全局变量。

无返回值。结束条件:节点为空。先增加深度,如果深度大于结果链表的长度,说明进入了新一层,此时需要把当前节点加入结果链表, 为了保证加入的节点是最右边的节点,需要先进入右子树,再进入左子树。

可以把全局变量depth变成递归参数。

class Solution {
    List<Integer> res = new ArrayList<>();
    // 记录递归的层数
    int depth = 0;

    public List<Integer> rightSideView_DFS(TreeNode root) {
        traverse(root);
        return res;
    }

    // 二叉树遍历函数
    void traverse(TreeNode root) {
        if (root == null) {
            return;
        }
        
        // 前序遍历位置
        depth++;
        // 第一次遇到这个深度。
        if (res.size() < depth) {
            // 这一层还没有记录值
            // 说明 root 就是右侧视图的第一个节点
            res.add(root.val);
        }
        // 注意,这里反过来,先遍历右子树再遍历左子树
        // 这样首先遍历的一定是右侧节点
        traverse(root.right);
        traverse(root.left);
        // 后序遍历位置
        depth--;
    }
}
  • 时间复杂度 : O(n)。最多访问每个结点一次,因此是线性复杂度。
  • 空间复杂度 : O(n)。最坏情况下,栈内会包含接近树高度的结点数量,占用 O(n) 的空间。