翻转二叉树
示例一:
Input: root = [4,2,7,1,3,6,9]
Output: [4,7,2,9,6,3,1]
示例二:
Input: root = [2,1,3]
Output: [2,3,1]
示例三:
Input: root = []
Output: []
树的结构:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
代码
方法一:前序遍历(根、左、右)
class Solution {
public TreeNode invertTree(TreeNode root) {
// 先序遍历--从顶向下交换,递归的形式进行交换
if(root==null){
return null;
}
//保存右子树
TreeNode rightTree=root.right;
//交换左右子树位置
root.right=invertTree(root.left);
root.left=invertTree(rightTree);
return root;
}
}
-
以一棵树的根为基准,交换左右;“invertTree(root.left);”和“invertTree(rightTree);”代表的是底层已经交换完了的左节点和右节点。“invertTree(root.left);”代表的是以root.left为根结点,交换root.left的左节点和右节点,他们的下面和“invertTree(rightTree);”也是差不多的原理。
-
一直下到最底部,存在左右节点的地方,对左右节点进行交换,自低向上交换,当回到最上面时,也就意味着底层已经翻转完成,只需要进行最后一次的根结点交换。
-
以根为基准,交换完才往下。
方法二:中序遍历(左、根、右)
class Solution {
public TreeNode invertTree(TreeNode root) {
// 中序遍历--从顶向下交换,递归的形式进行交换
if(root==null){
return null;
}
//递归找到左节点
invertTree(root.left);
//保存右节点
TreeNode righttree=root.right;
root.right=root.left;
root.left=righttree;
// 递归找到右节点 继续交换 :
//因为此时左右节点已经交换了,所以此时的右节点为root.left
invertTree(root.left);
return root;
}
}
-
一路往下去,到左子树拥有左节点或者右节点或者左右节点的最下根结点,开始交换左右子节点。
-
交换完以后,此时进行判断翻转的只有父节点的左子树下面的子节点,右子树下的子节点还没有交换,所有需要右子树下的字节点翻转,但是经过上面的交换,左右子树已经交换了位置,所有进行交换的还是左子树(为原来的右子树)。
-
(先处理好左子树的情况情况,回到根结点,交换左右,才处理原来的右节点的子节点的情况)
第三种:后序遍历(左、右、根)
class Solution {
public TreeNode invertTree(TreeNode root) {
// 后序遍历-- 从下向上交换
if(root==null){
return null;
}
TreeNode leftNode=invertTree(root.left);
TreeNode rightNode=invertTree(root.right);
root.left=rightNode;
root.right=leftNode;
return root;
}
}
- 交换完左右才回到根,一直自底向上循环上去。
2. 为什么叫前序、后序、中序
一棵二叉树由根结点、左子树和右子树三部分组成,若规定 D、L、R 分别代表遍历根结点、遍历左子树、遍历右子树,则二叉树的遍历方式有 6 种:DLR、DRL、LDR、LRD、RDL、RLD。由于先遍历左子树和先遍历右子树在算法设计上没有本质区别,所以,只讨论三种方式:
-
DLR–前序遍历(根在前,从左往右,一棵树的根永远在左子树前面,左子树又永远在右子树前面 )
-
LDR–中序遍历(根在中,从左往右,一棵树的左子树永远在根前面,根永远在右子树前面)
-
LRD–后序遍历(根在后,从左往右,一棵树的左子树永远在右子树前面,右子树永远在根前面)
- 根是相对的,对于整棵树而言只有一个根,但对于每棵子树而言,又有自己的根。比如对于下面个图,对于整棵树而言,A是根,A分别在最前面、中间、后面被遍历到。而对于D,它是G和H的根,对于D、G、H这棵小树而言,顺序分别是DGH、GDH、GHD;对于C,它是E和F的根,三种排序的顺序分别为: CEF、ECF、EFC。是不是根上面的DLR、LDR、LRD一模一样呢~~
- 整棵树的起点,就如上面所说的,从A开始,前序遍历的话,一棵树的根永远在左子树前面,左子树又永远在右子树前面,你就找他的起点好了。
- 二叉树结点的先根序列、中根序列和后根序列中,所有叶子结点的先后顺序一样
参考:https://leetcode-cn.com/problems/invert-binary-tree/comments/
https://haoqchen.site/2018/05/23/go-through-binary-tree/