【算法】二叉树的右视图

【算法】二叉树的右视图

出处

letCode 299:https://leetcode-cn.com/problems/binary-tree-right-side-view/

题解地址可参考:https://leetcode-cn.com/problems/binary-tree-right-side-view/solution/er-cha-shu-de-you-shi-tu-by-leetcode-solution/

题目

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

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

思路

深度优先搜索

我们对树进行深度优先搜索,在搜索过程中,我们总是先访问右子树。那么对于每一层来说,我们在这层见到的第一个结点一定是最右边的结点。这样一来,我们可以存储在每个深度访问的第一个结点,一旦我们知道了树的层数,就可以得到最终的结果数组。

广度优先搜索

我们可以对二叉树进行层次遍历,那么对于每层来说,最右边的结点一定是最后被遍历到的。

代码

二叉树的定义

首先要知道二叉树的定义,它的每个节点都包含一个左节点和右节点:

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode() { }
    
    TreeNode(int val) {
        this.val = val;
    }
    
    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

深度优先算法

1、定义一个HashMap,存放右视图下的节点

2、创建一个节点栈,存放当前遍历到的节点,并把根节点压入栈

3、创建一个深度栈,存放每个节点对应的深度,并把当前节点深度压入栈

4、遍历节点栈,对节点栈进行出栈操作

5、每次遍历,都取出节点栈和深度栈的栈顶元素

6、如果出栈的节点不为null,且HashMap中不存在对应深度的节点,就把该节点插入到HashMap中,然后继续将当前节点的左节点和右节点分别压入节点栈中,将depth + 1的值压入深度栈中

7、如果最终栈已经没有元素,则循环结束,然后将map中记录的每层的右节点转移到list上,并返回list

深度优先算法:
public List<Integer> rightSideView(TreeNode root) {
        // 定义一个HashMap,存放右视图下的节点
        Map<Integer, Integer> map = new HashMap<>();
        // 定义一个节点栈,存放当前遍历到的节点
        Deque<TreeNode> nodeStack = new ArrayDeque<>();
        // 定义一个深度栈,存放每个节点对应的深度
        Deque<Integer> depthStack = new ArrayDeque<>();

        int maxDepth = -1;

        // 节点栈先压入根节点
        nodeStack.push(root);
        // 深度栈压入
        depthStack.push(0);

        // 遍历节点栈
        while (!nodeStack.isEmpty()) {
            // 取出节点栈中的栈顶元素
            TreeNode node = nodeStack.pop();
            // 取出深度栈中的栈顶元素
            int depth = depthStack.pop();

            if (node != null) {
                // 维护二叉树的最大深度
                maxDepth = Math.max(maxDepth, depth);
                // 如果不存在对应深度的节点,才把该节点插入到map中
                if (!map.containsKey(depth)) {
                    map.put(depth, node.val);
                }
                // 将当前节点的左节点和右节点分别压入节点栈中
                nodeStack.push(node.left);
                nodeStack.push(node.right);
                // 将depth + 1的值压入深度栈中
                depthStack.push(depth + 1);
                depthStack.push(depth + 1);
            }
        }

        // 将map中记录的每层的右节点转移到list上
        List<Integer> rightView = new ArrayList<>();
        for (int d = 0; d <= maxDepth; d++) {
            rightView.add(map.get(d));
        }

        // 返回这个list
        return rightView;
    }

广度优先算法

1、定义一个HashMap,存放右视图下的节点

2、创建一个节点队列,存放当前遍历到的节点,根节点先入队

3、创建一个深度队列,存放每个节点对应的深度,深度0先入队

4、遍历节点队列,对节点队列进行出队操作

5、每次遍历,都取出节点队列和深度队列的头部元素

6、如果出队的节点不为null,就把该节点插入到HashMap中,然后继续将当前节点的左节点和右节点分别入队,将depth + 1的值入队

7、如果最终队列已经没有元素,则循环结束,然后将map中记录的每层的右节点转移到list上,并返回list

广度优先算法:
public List<Integer> rightSideView(TreeNode root) {
    // 创建一个HashMap, 存放右视图下的节点
    Map<Integer, Integer> map = new HashMap<>();
    // 创建一个节点队列,存放当前遍历到的节点
    Queue<TreeNode> nodeQueue = new ArrayDeque<>();
    // 创建一个深度队列,存放每个节点对应的深度
    Queue<Integer> depthQueue = new ArrayDeque<>();
    int maxDepth = -1;
    // 节点队列:根节点先入队
    nodeQueue.add(root);
    // 深度队列:深度0先入队
    depthQueue.add(0);

    // 遍历节点队列
    while (!nodeQueue.isEmpty()) {
        // 取出节点队列的头部元素
        TreeNode node = nodeQueue.remove();
        // 取出深度队列的头部元素
        int depth = depthQueue.remove();

        // 如果头部节点不为nul
        if (node != null) {
            // 维护二叉树的最大深度
            maxDepth = Math.max(maxDepth, depth);

            // 由于每一层最后一个访问到的节点才是我们要的答案,因此不断更新对应深度的信息即可
            map.put(depth, node.val);

            // 将当前节点的左节点和右节点分别入节点队列
            nodeQueue.add(node.left);
            nodeQueue.add(node.right);
            // 将depth + 1的值入深度队列两次
            depthQueue.add(depth + 1);
            depthQueue.add(depth + 1);
        }
    }

    // 将map中记录的每层的右节点转移到list上
    List<Integer> rightView = new ArrayList<Integer>();
    for (int depth = 0; depth <= maxDepth; depth++) {
        rightView.add(map.get(depth));
    }

    // 返回这个list
    return rightView;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一场雪ycx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值