后序遍历:只有后序遍历才能将左右孩子的信息返回给根节点;需要收集孩子信息向上一层节点返回的都是后序遍历
前序后序可以,中序不行
!](https://img-blog.csdnimg.cn/1e0526a7bcc048c1876a7b56e6c99072.png)
其中红色代表当前处理的节点,在遍历时,处理动作为加入到result集合中,在翻转中,处理动作为swap(node.left, node.right)
代码如下:(非递归)
public TreeNode invertTree(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
if(root != null) stack.push(root);
while(stack.size() > 0){
TreeNode node = stack.peek();
if(node != null){
node = 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();
swap(node.left, node.right, node);
}
}
return root;
}
void swap(TreeNode n1, TreeNode n2, TreeNode root){
root.left = n2;
root.right = n1;
}
代码如下:(递归版)
public TreeNode invertTree(TreeNode root) {
dfs(root);
return root;
}
void dfs(TreeNode root){
if(root == null) return;
dfs(root.left);
dfs(root.right);
swap(root.left, root.right, root);
}
void swap(TreeNode n1, TreeNode n2, TreeNode root){
root.left = n2;
root.right = n1;
}
后序遍历:只有后序遍历才能将左右孩子的信息返回给根节点;需要收集孩子信息向上一层节点返回的都是后序遍历
关键: 判断根节点的左右孩子是否可以相互翻转
public boolean isSymmetric(TreeNode root) {
if(root == null) return false;
return compare(root.left, root.right);
}
public boolean compare(TreeNode n1, TreeNode n2){
//停止条件
if(n1 == null && n2 == null) return true;
if(n1 == null || n2 == null) return false;
if(n1.val != n2.val) return false;
//对于n1和n2来说,n1:左右根;n2:右左根 都是后序遍历
boolean b1 = compare(n1.left, n2.right);
boolean b2 = compare(n1.right, n2.left);
boolean b3 = b1 && b2; //根
return b3;
}
左子树遍历:左右根;右子树遍历:右左根;都是后序遍历。
因为你不可能不遍历左右孩子就知道根节点是不是对称的
前序遍历:
int res = 0;
public int maxDepth(TreeNode root) {
DD(root, 0);
return res;
}
public void DD(TreeNode node, int cur){
if(node == null){
res = Math.max(res, cur);
return;
}
//cur++; //根
DD(node.left, cur+1); //左
DD(node.right, cur+1); //右
}
转化为求二叉树的最大高度:即根节点的高度(后序遍历)
public int maxDepth(TreeNode root) {
if(root == null) return 0;
int ll = maxDepth(root.left); //左
int rr = maxDepth(root.right); //右
return Math.max(ll, rr)+1; //根
}
最小深度是从根节点到最近叶子节点的最短路径上的节点数量
前序遍历:
int res = 0x3f3f3f3f;
public int minDepth(TreeNode root) {
if(root == null) return 0;
DD(root, 1);
return res;
}
public void DD(TreeNode node, int cur){
//停止条件:叶子节点
if(node.left == null && node.right == null){
res = Math.min(res, cur);
return;
}
//cur++; //根
if(node.left != null) DD(node.left, cur+1); //左
if(node.right != null) DD(node.right, cur+1); //右
}
层序遍历
public int minDepth(TreeNode root) {
int res = 0;
Deque<TreeNode> dq = new ArrayDeque<>();
if(root != null) dq.addLast(root);
while(!dq.isEmpty()){
res++;
int size = dq.size();
while(size-- > 0){
TreeNode node = dq.pollFirst();
if(node.left == null && node.right == null) return res;
if(node.left != null) dq.addLast(node.left);
if(node.right != null) dq.addLast(node.right);
}
}
return res;
}
后序遍历:转化为求叶子节点的最小高度
public int minDepth(TreeNode root){
if(root == null) return 0;
if(root.left == null && root.right == null) return 1;
int ll = 0x3f3f3f3f;
int rr = 0x3f3f3f3f;
if(root.left != null) ll = minDepth(root.left); //左
if(root.right != null) rr = minDepth(root.right); //右
int gg = Math.min(ll, rr)+1; //根
return gg;
}
加一个root.left == null && root.right == null的返回条件,是因为最小深度的定义是到叶子节点的节点数,如果不加,遇到left为null而right不为null的node,会认为这个node的高度为1