Leetcode 199 二叉树的右视图

最近依旧每天在刷一道新题的同时复习一道忘了的旧题,今天复习的忘了的旧题就是leetcode 199 二叉树的右视图,我的确忘了具体代码怎么写了,但是我记得这是我当初第一次真正意义上自己思考并写出来的一道中等题,还是记忆犹新的。

给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]

解释:
1 <—
/
2 3 <—
\
5 4 <—

起初我以为这道题只需要输出二叉树的右孩子和root就可以了,所以直接不过脑子的写了一串代码,结果答案错误很尴尬,的确,稍微认真审题就会发现,这道题需要的是从右边看整个二叉树,自然假设没有右孩子那就只能看左孩子了。
所以这道题写题解之前,我们先看另一道题,“统计一颗二叉树的宽度”,我看了B站上左成云大佬的课程,发现了一个除了队列(Queue)以外不需要其他数据结构的算法。

就是先记住‘当前层的最右结点’,‘下一层的最右结点’,‘最大节点数’
队列的用法和层序遍历一致,这里不多解释,每次出队的结点的左右孩子判断是否为空之后,‘最右结点’ 的指针都会指向最右边的孩子,最后在根据当前结点是否是上一层已经确定的最右结点进行判断,并统计当前层的节点数。

上代码

public static int maxWidth(TreeNode head){
        
        if(head == null){
            return -1;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(head);
        int curLevelNodes = 0;
        TreeNode curEnd = head;//当前层的最右结点
        TreeNode nextEnd = null;//下一层的最右结点
        int max = 0;//标记最大结点数目
        while(!queue.isEmpty()){
            //不为空继续
            TreeNode cur = queue.poll();//出队
            
            if(cur.left != null){
                //如果左孩子不为空
                queue.add(cur.left);
                nextEnd = cur.left;//指针往右移
            }
            if(cur.right != null){
                //右孩子也有的话
                queue.add(cur.right);
                nextEnd = cur.right;//指针继续往右移
            }
            
            curLevelNodes ++;
            if(cur == curEnd){
                //如果当前结点是这一层的最后一个结点,准备结算
                max = Math.max(max,curLevelNodes);
                curEnd = nextEnd;//因为当前是本层最后一个结点,所以相应的下一层最后一个节点也确定好了
                curLevelNodes = 0;//清零
            }
            
        }
        return max;
    }
建立一种发现层的机制

所以通过这道题的答案我们对上一道题进行一下联想,不满发现其中的记录最右结点的机制很是好用,于是我们的灵感就来了

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> list = new ArrayList();//输出数组,这里根据返回值设置为List对象

        if(root == null){
            return list;//如果为空就直接扔出去
        }

        Queue<TreeNode> queue = new LinkedList<>();//定义一个队列用来进行层次遍历

        queue.add(root);//放入头结点

        TreeNode curEnd = root;//设置好当前最右结点
        TreeNode nextEnd = root;//设置好下一层最右结点,但是没关系,其实指向空应该也没问题;

        while(!queue.isEmpty()){
            //如果队列不为空,出队进行层次遍历
            TreeNode cur = queue.poll();//当前结点

            //下面是准备设置下一层最右结点
            if(cur.left != null){
                queue.add(cur.left);//常规入队

                //重点来了
                nextEnd = cur.left;
            }
            //同理
            if(cur.right != null){
                queue.add(cur.right);

                nextEnd = cur.right;//同理
            }
            //此时已经确立了下一层最右边的结点,那么我们可以判断当前结点是否是本层的最右结点(本层的最右节点在上一层就已经找到了)
            if(cur == curEnd){
                list.add(curEnd.val);//放入队列
                curEnd = nextEnd;//设置下一层的最右结点
            }
        }

        return list;


        

    }

}

解释都在注解中

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值