二叉树的层序遍历、翻转二叉树、对称二叉树、二叉树的最大深度

15 阅读4分钟

102. 二叉树的层序遍历

  这题需要将每一层的数返回,一层是一个数组,所以需要嵌套使用。且二叉树本身不能存储数据,所以我们要借助栈来实现。代码如下:

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> que=new LinkedList<>();
        List<List<Integer>> result=new ArrayList<>();
        if(root!=null){
            que.offer(root);
        }
        while(!que.isEmpty()){
            List<Integer> list=new ArrayList<>();
            int size=que.size();
            while(size!=0){
                TreeNode node=que.poll();
                list.add(node.val);
                if(node.left!=null){
                    que.offer(node.left);
                }
                if(node.right!=null){
                    que.offer(node.right);
                }
                size--;
            }
                result.add(list);
        }
        return result;
    }
}

        函数首先创建一个队列 Queue<TreeNode> 用来进行广度优先搜索,同时创建一个 List<List<Integer>> result 用来存储最终结果。如果根节点 root 不为空,就先把根节点加入队列。接下来进入循环,只要队列不为空就继续遍历。每一次循环代表处理树的一层,先通过 int size = que.size() 记录当前队列中的节点数量,这个数量就是当前层的节点个数。然后创建一个新的 List<Integer> list 用来存储这一层的所有节点值。接着通过 while(size != 0) 循环依次取出这一层的节点,每次用 que.poll() 从队列中取出队头节点,并把该节点的值 node.val 加入 list 中。如果这个节点存在左孩子,就把左孩子加入队列;如果存在右孩子,就把右孩子也加入队列,这样下一层的节点就被依次放入队列中。每处理完一个节点就让 size--,直到当前层所有节点都处理完。当前层遍历结束后,把这一层的 list 加入到结果列表 result 中。然后继续处理队列中的下一层节点。最终当队列为空时说明整棵树已经遍历完成,函数返回 result,其中每个子列表都表示二叉树的一层节点。

226. 翻转二叉树

        这道题这段代码实现的是二叉树的镜像翻转,也就是把二叉树中每个节点的左子树和右子树进行交换。我们有三种方法,前序遍历、后序遍历、中序遍历。代码如下:

前序遍历:

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

        使用的是递归思想。首先判断当前节点 root 是否为空,如果为空说明已经遍历到叶子节点的下方,没有需要处理的节点,直接返回 root。如果节点不为空,就调用 swap(root) 方法,将当前节点的左孩子和右孩子进行交换。swap 方法通过一个临时变量 temp 保存原来的左孩子,然后把右孩子赋值给 root.left,再把原来的左孩子赋值给 root.right,从而完成左右子树的交换。交换完当前节点的左右子树后,再分别对新的左子树 invertTree(root.left) 和新的右子树 invertTree(root.right) 继续递归执行同样的操作,这样整棵树的每个节点都会完成左右子树的交换。最后返回根节点 root,此时整棵二叉树已经被翻转成它的镜像结构。

后序遍历:

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

        只是把swap函数移到了后面。

        那么中序遍历只需把swap移到中间就行了吗?答案是:不是的。

       中序遍历是中左右,首先在左子树中会把1,3交换,变成3,1,之后交换2,7,变成7,2,此时是

        此时交换右边是3,1,相当于交换了两次。所以我们要把invertTree(root.right);写为invertTree(root.left);代码如下:

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

101. 对称二叉树

        这题比较简单,我们要比较左右子树是否相同,我们把左子树的左边和右子树的右边称为外侧,左子树的右边和右子树的左边成为内侧,我们要比较的是外侧是否相同,内侧是否相同。我们可以分为以下几类:1.左右子树都为空,则返回true。2.左右子树都不为空,但值不相同,返回false。3.左为空右不为空,返回false。4.左不为空,右为空,返回false。代码如下:

class Solution {
    public boolean isSymmetric(TreeNode root) {
        return compare(root.left,root.right);
    }
    public boolean compare(TreeNode left,TreeNode right){
        if(left==null&&right==null){
            return true;
        }else if(left==null&&right!=null){
            return false;
        }else if(left!=null&&right==null){
            return false;
        }else if(left.val!=right.val){
            return false;
        }
        boolean outside=compare(left.left,right.right);
        boolean inside=compare(left.right,right.left);
        return outside&&inside;
    }
}

        我们分别比较外侧内侧,并将结果返回。

104. 二叉树的最大深度

        首先要理解高度和深度,那很接单==简单,高度就是从下往上数,深度是从下往上数,但其实你看最大的高度和深度是一样的,所以我们这题可以用求高度的办法来写,代码如下:

class Solution {
    public int maxDepth(TreeNode root) {
        return getHeight(root);
    }
    public int getHeight(TreeNode root){
        if(root==null){
            return 0;
        }
        int leftHeight=getHeight(root.left);
        int rightHeight=getHeight(root.right);
        return Math.max(leftHeight,rightHeight)+1;
    }
}

        这题使用后序遍历来写,每次返回的高度加一,表示比下面高一层。