文章目录
问题描述
翻转一棵二叉树。
示例:
输入:
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;
}
}