每日五题(3)

剑指Offer 32-II.从上到下打印二叉树II

在这里插入图片描述

解析过程:

题目要求已经很明确了,我们需要对二叉树进行层序遍历,但这时候要注意返回值是一个嵌套链表,需要对二叉树进行按行打印,所以我们就得找个东西来存放每一行。

队列就是一个比较好的选择了!当根节点不是空的时候,那就将根节点先放入队列。当我们要往list中放的时候就将其取出,然后再将该节点的子节点放入到队列中。我们可以使用for循环来控制每一层的遍历,并且用队列的长度来控制循环。当我们将二叉树遍历完成时那么队列也就一定为空了,所以这可以当做我们BFS的结束条件。

代码实现:

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> res = new LinkedList<>();
        if(root != null) queue.add(root);
        while(!queue.isEmpty()){
            List<Integer> list = new LinkedList<>();
            for(int i = queue.size();i > 0;i--){
                TreeNode node = queue.remove();
                list.add(node.val);
                if(node.left != null)queue.add(node.left);
                if(node.right != null)queue.add(node.right);
            }
            res.add(list);
        }
        return res;
    }
}

剑指Offer 32-I.从上到下打印二叉树

在这里插入图片描述

在这里插入图片描述

题目解析:

其实我挺不明白为什么第一道题,也就是刚才那道题难度被列为简单,而这道题被列为中等,你是不是也很迷惑?

如果刚才那道题你明白了,那么这道题就是小菜一碟,不过要注意,因为我们不知道二叉树中到底有多少个元素,所以我们可以先遍历一遍二叉树,查看其元素个数,再进行层序遍历。也可以像我下面写的这种,先进行层序遍历,将遍历之后的结果放在一个list中,之后再挪到数组中返回。

代码实现:

class Solution {
    public int[] levelOrder(TreeNode root) {
        if(root == null) return new int[0];
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        List<Integer> arrayList = new ArrayList<>();
        while(!queue.isEmpty()){
            TreeNode node = queue.remove();
            arrayList.add(node.val);
            if(node.left != null)queue.add(node.left);
            if(node.right != null)queue.add(node.right);
        }
        int size = arrayList.size();
        int[] res = new int[size];
        for(int i = 0;i < size;i++){
            res[i] = arrayList.get(i);
        }
        return res;
    }
}

剑指Offer 32-III.从上到下打印二叉树III

在这里插入图片描述

前提须知:

在这里插入图片描述

解析过程:

请注意看上图,如果你对双端队列足够了解,那么这道题就游刃而解了。

很明显,这道题依然是前两道题的变形,那么唯一要注意的就是之字形这个点,可以理解为第一行从左到右打印,第二行从右到左打印,第三行从左到右打印。。。。可得规律奇数行,从左到右,偶数行从右到左,从左到右其实我们已经做出来了,就是队列啊,那从右到左呢?当然是栈啦!双端队列既可以当做队列,也可以当做栈用,所以这个时候我们只要做好标记,当前遍历的是奇数行还是偶数行即可。

双端队列当做队列时,是按照addLast添加元素;当做栈时,按照addFirst添加,元素顺序就是倒序的了。

代码实现:

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> res = new LinkedList<>();
        if(root != null) queue.add(root);
        int flag = 1;
        while(!queue.isEmpty()){
            LinkedList<Integer> list = new LinkedList<>();
            for(int i = queue.size();i > 0;i--){
                TreeNode node = queue.remove();
                if(flag % 2 == 1)list.addLast(node.val);
                else list.addFirst(node.val);
                if(node.left != null)queue.add(node.left);
                if(node.right != null) queue.add(node.right);
            }
            flag++;
            res.add(list);
        }
        return res;
    }
}

剑指Offer27.二叉树的镜像

在这里插入图片描述

解析过程:

这道题可以使用递归的方式去做,首先整体的思路就是将左子树与右子树交换,直到交换到叶子结点位置,开始返回。

当然也可以配合使用栈或者队列来操作。

代码实现:

class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if(root == null) return null;
        TreeNode node = root.left;
        root.left = mirrorTree(root.right);
        root.right = mirrorTree(node);
        return root;
    }
}

剑指Offer 68-I.二叉搜索树的最近公共祖先

在这里插入图片描述

解析过程:

首先要注意两个条件:1.这是一颗二叉搜索树;2.所有节点的值都是唯一的。

这就意味着左孩子一定小于根节点,右孩子一定大于根节点。而现在要判断最近公共祖先,那么也就只有三种情况了

1.如果两个孩子都大于根,那么结果一定在右子树

2.如果两个孩子都小于根,那么结果一定在左子树

3.如果两个孩子分别位于左右子树,或者有一个等于根,那么就找到了。

代码实现:

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        TreeNode cur = root;
        while(cur != null){
            if(cur.val < p.val && cur.val < q.val){
                cur = cur.right;
            }else if(cur.val > p.val && cur.val > q.val){
                cur = cur.left;
            }else{
                break;
            }
        }
        return cur;
    }
}

注:明天想写一写topK~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值