【二叉树 1.3】226.翻转二叉树

132 阅读3分钟

文章目录

问题描述

翻转一棵二叉树。

示例:

输入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9

输出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1

解决方案1:递归(前序遍历 + 后序遍历)

我们来看一下递归三部曲:

确定递归函数的参数和返回值

参数就是要传入节点的指针,不需要其他参数了,通常此时定下来主要参数,如果在写递归的逻辑中发现还需要其他参数的时候,随时补充。

返回值的话其实也不需要,但是题目中给出的要返回root节点的指针,可以直接使用题目定义好的函数,所以就函数的返回类型为TreeNode*。

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);

基于这递归三步法,代码基本写完,代码如下(前序):

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;   // 最后返回二叉树的根,所以递归的的时候不能接受返回值,只要不接收,则递归的返回值无效
    }
}

解决方案2:统一写法迭代法(前序遍历 + 后序遍历)

白板面试要求写代码的时候,是要求写对,所以迭代法只要学会一种理解的最深的就好了

前序遍历,代码如下:

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root==null) return null;
        Stack<TreeNode> stack=new Stack<TreeNode>();
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode node=stack.peek(); // 最上面那个
            if (node != null){
                stack.pop();
                if (node.right!=null) stack.push(node.right);
                if (node.left!=null) stack.push(node.left);
                stack.push(node);
                stack.push(null);
            }else{
                stack.pop();
                node=stack.pop();
                TreeNode temp = node.left;
                node.left = node.right;
                node.right=temp;
            }
        }
        return root;   // 最后返回根节点
    }
}

后序遍历-统一写法,如下:

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root==null) return null;   // 有了这一句,后面的stack.push就不需要 if(null != root) 判断了,三种递归遍历和层序遍历都是这样,如果root为null,就直接返回null
        Stack<TreeNode> stack=new Stack<TreeNode>();
        stack.push(root);
        while (!stack.isEmpty()){
            TreeNode node=stack.peek(); // 最上面那个  不是弹出
            if (node != null){
                stack.pop();
                stack.push(node);
                stack.push(null);
                if (node.right!=null) stack.push(node.right);
                if (node.left!=null) stack.push(node.left);
            }else{
                stack.pop();
                node=stack.pop();
                TreeNode temp = node.left;
                node.left = node.right;
                node.right=temp;
            }
        }
        return root;
    }
}

解决方案3: 层序遍历

层数遍历也是可以翻转这棵树的,因为层序遍历也可以把每个节点的左右孩子都翻转一遍,代码如下:

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root==null) return null;
        Queue<TreeNode> queue=new LinkedList<>();
        queue.offer(root);  // 插入根节点,就是插入第一个
        while (!queue.isEmpty()){
            int size=queue.size();
            for (int i=0;i<size;i++) {
                TreeNode node = queue.poll(); // 最上面那个
                TreeNode temp = node.left;
                node.left = node.right;
                node.right = temp;
                invertTree(root.left);
                invertTree(root.right);
            }
        }
        return root;
    }
}