算法刷题|二叉树的层序遍历、226.翻转二叉树、101.对称二叉树

二叉树层序遍历

层序遍历

题目:给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

思路:使用一个size记录每一层的数量,然后进行输出

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new LinkedList<>();
        if(root == null){
            return res;
        }
        Deque<TreeNode> deque = new ArrayDeque<>();
        deque.addLast(root);
        while(!deque.isEmpty()){
            int size = deque.size();// 记录每一层有多少个元素
            List<Integer> ans = new LinkedList<>();
            while(size --> 0){
                TreeNode node = deque.pollFirst();
                ans.add(node.val);
                if(node.left != null){// 将左孩子入队
                    deque.addLast(node.left);
                }
                if(node.right != null){// 将右孩子入队
                    deque.addLast(node.right);
                }
            }
            res.add(ans);
        }
        return res;
    }
}

层序遍历||

题目:给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

方法一

直接在上面代码return之前反转一下list即可:Collections.reverse(res);

方法二
在插入结果集合的时候始终往第一个位置插入即可

class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
            List<List<Integer>> res = new LinkedList<>();
        if(root == null){
            return res;
        }
        Deque<TreeNode> deque = new ArrayDeque<>();
        deque.addLast(root);
        while(!deque.isEmpty()){
            int size = deque.size();// 记录每一层有多少个元素
            List<Integer> ans = new LinkedList<>();
            while(size --> 0){
                TreeNode node = deque.pollFirst();
                ans.add(node.val);
                if(node.left != null){// 将左孩子入队
                    deque.addLast(node.left);
                }
                if(node.right != null){// 将右孩子入队
                    deque.addLast(node.right);
                }
            }
            res.add(0,ans);// 这里始终插入在0位置,最后就实现了从底层开始输出的效果
        }
        return res;
    }
}

二叉树的右视图

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

思路:还是层序遍历,就是在每一次的最右一个元素就是最右侧的元素

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> res = new LinkedList<>();
        if(root == null){
            return res;
        }
        Deque<TreeNode> deque = new ArrayDeque<>();
        deque.addLast(root);
        while(!deque.isEmpty()){
            int size = deque.size();// 还是需要记录一下每一层的大小,最后一个就是最右侧的元素
            for(int i = 0;i<size;i++){
                TreeNode node = deque.pollFirst();
                if(i == size - 1){// 最后一个就是最右侧的元素
                    res.add(node.val);
                }
                if(node.left != null){
                    deque.addLast(node.left);
                }
                if(node.right != null){
                    deque.addLast(node.right);
                }               
            }  
        }
        return res;
    }
}

二叉树的层平均值

题目:给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。

思路:层序遍历,然后每层统计一下平均值

class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> res = new LinkedList<>();
        if(root == null){
            return res;
        }
        Deque<TreeNode> deque = new ArrayDeque<>();
        deque.addLast(root);
        while(!deque.isEmpty()){
            double sum = 0d;
            int size = deque.size();
            for(int i = 0;i<size;i++){
                TreeNode node = deque.pollFirst();
                sum+=node.val;
                if(node.left != null){
                    deque.addLast(node.left);
                }
                if(node.right != null){
                    deque.addLast(node.right);
                }
            }
            res.add(sum/size);
        }
        return res;
    }
}

N叉树的层序遍历

题目:给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

思路:使用队列存放元素,二叉树是在出队的时候将其左右孩子入队,这里就是将其所有孩子节点入队

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> res = new LinkedList<>();
        if(root == null){
            return res;
        }
        Deque<Node> deque = new ArrayDeque<>();
        deque.addLast(root);
        while(!deque.isEmpty()){
            List<Integer> ans = new LinkedList<>();
            int size = deque.size();
            while(size --> 0){
                Node node = deque.pollFirst();
                ans.add(node.val);
                if(node.children != null){
                    for(Node n : node.children){
                        deque.addLast(n);
                    }
                }
            }
            res.add(ans);
        }
        return res;
    }
}

在每个树行中找到最大值

题目:给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。

思路:依旧是层序遍历,在每一行中找最大值

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        List<Integer> res = new LinkedList<>();
        if(root == null){
            return res;
        }
        Deque<TreeNode> deque = new ArrayDeque<>();
        deque.addLast(root);
        while(!deque.isEmpty()){
            int size = deque.size();
            int max = Integer.MIN_VALUE;
            while(size --> 0){
                TreeNode node = deque.pollFirst();
                max = Math.max(max,node.val);
                if(node.left != null){
                    deque.addLast(node.left);
                }
                if(node.right != null){
                    deque.addLast(node.right);
                }
            }
            res.add(max);
        }
        return res;
    }
}

填充每个节点的下一个右节点指针

题目:给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点

思路:层序遍历,将每一层的前n-1个元素连接起来,最后一个元素指向null

class Solution {
    public Node connect(Node root) {
        if(root == null){
            return root;
        }
        Deque<Node> deque = new ArrayDeque<>();
        deque.addLast(root);
        while(!deque.isEmpty()){
            int size = deque.size();
            for(int i = 0;i<size;i++){
                Node node = deque.pollFirst();
                if(i < size - 1){// 只连接每一层的,这个判断防止当前层的最后一个元素连接到下一层的第一个元素了
                    node.next = deque.peek();
                }
                if(node.left != null){
                    deque.addLast(node.left);
                }
                if(node.right != null){
                    deque.addLast(node.right);
                }
            }
        }
        return root;
    }
}

填充每个节点的下一个右节点指针||

题目:填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL 。
初始状态下,所有 next 指针都被设置为 NULL 。

同上

class Solution {
    public Node connect(Node root) {
        if(root == null){
            return null;
        }
        Deque<Node> deque = new ArrayDeque<>();
        deque.addLast(root);
        while(!deque.isEmpty()){
            int size = deque.size();
            for(int i = 0;i<size;i++){
                Node node = deque.pollFirst();
                if(i < size - 1){
                    node.next = deque.peek();
                }
                if(node.left != null){
                    deque.addLast(node.left);
                }
                if(node.right != null){
                    deque.addLast(node.right);
                }
            }
        }
        return root;
    }
}

二叉树的最大深度

题目:给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点

思路:层序遍历,每一层统计高度

class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null){
            return 0;
        }
        Deque<TreeNode> deque = new ArrayDeque<>();
        deque.addLast(root);
        int depth = 0;
        while(!deque.isEmpty()){
            int size = deque.size();
            while(size --> 0){
                TreeNode node = deque.pollFirst();
                if(node.left != null){
                    deque.addLast(node.left);
                }
                if(node.right != null){
                    deque.addLast(node.right);
                }
            }
            depth++;
        }
        return depth;
    }
}

二叉树的最小深度

题目:给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。

思路:层序遍历,遇到了左右孩子都为null的时候,说明遇到了叶子节点,可以返回深度了

class Solution {
    public int minDepth(TreeNode root) {
        if(root == null){
            return 0;
        }
        Deque<TreeNode> deque = new ArrayDeque<>();
        deque.addLast(root);
        int depth = 1;// 因为根节点不为空,所有从1开始
        while(!deque.isEmpty()){
            int size = deque.size();
            while(size --> 0){
                TreeNode node = deque.pollFirst();
                if(node.left == null && node.right == null){// 遇到了叶子节点
                    return depth;
                }
                if(node.left != null){
                    deque.addLast(node.left);
                }
                if(node.right != null){
                    deque.addLast(node.right);
                }
            }
            depth++;
        }
        return depth;
    }
}

翻转二叉树

题目:给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

递归

思路:使用递归的方式,然后采用前序或者后序遍历进行交换节点

前序遍历

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

后序遍历

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

中序遍历

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root == null){
            return null;
        }
        invertTree(root.left);
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        invertTree(root.left);// 中序遍历的话,这里就不能是右子树了,因为当前的右子树是反转前的左子树(已经被交换过了),当前的左子树是反转前的右子树(还没有反转的节点)
        return root;
    }
}

迭代

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root == null){
            return null;
        }
        Deque<TreeNode> deque = new ArrayDeque<>();
        deque.addLast(root);
        while(!deque.isEmpty()){
            int size = deque.size();
            while(size --> 0){
                TreeNode node = deque.pollFirst();
                TreeNode temp = node.left;
                node.left = node.right;
                node.right = temp;
                if(node.left != null){
                    deque.addLast(node.left);
                }
                if(node.right != null){
                    deque.addLast(node.right);
                }
            }
        }
        return root;
    }
}

对称二叉树

题目:给你一个二叉树的根节点 root , 检查它是否轴对称。

递归

思路:采用后序遍历,判断左右孩子是否相等

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null){
            return true;
        }
        return compare(root.left,root.right);
    }
    private boolean compare(TreeNode left,TreeNode right){
        if(left != null && right == null){
            return false;
        }else if(left == null && right != null){
            return false;
        }else if(left == null && right == null){
            return true;
        }else if(left.val != right.val){
            return false;
        }else{// 左右两个节点的值相等,就往下继续遍历
        	// 左  右
            boolean outSide = compare(left.left,right.right);// 判断外侧是否相等
            // 右 左
            boolean inSide = compare(left.right,right.left);//判断内侧是否相等
            // 中
            return outSide && inSide;
        }
    }
}

迭代

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null){
            return true;
        }
        Deque<TreeNode> deque = new LinkedList<>();
        deque.addLast(root.left);
        deque.addLast(root.right);
        while(!deque.isEmpty()){
            TreeNode l = deque.pollFirst();
            TreeNode r = deque.pollFirst();
            if(l == null && r == null){
                continue;// 此处不能返回true,因为虽然当前节点相同,但是可能后面的左右子树存在不是对称的
            }
            if(l != null && r == null){
                return false;
            }
            if(l == null && r != null){
                return false;
            }
            if(l.val != r.val){
                return false;
            }
            deque.addLast(l.left);
            deque.addLast(r.right);

            deque.addLast(l.right);
            deque.addLast(r.left);
        }
        return true;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值