今日收获(优先掌握递归法):翻转二叉树,对称二叉树,求最大/最小深度
1. 翻转二叉树
题目链接:226. - 力扣(LeetCode)
思路:递归函数的作用是交换两个节点的左右子树。如果当前节点为空则返回,交换完当前节点后再递归调用传入左右节点
方法:
class Solution {
public TreeNode invertTree(TreeNode root) {
swapNode(root);
return root;
}
// 重复交换节点的左右子树
public void swapNode(TreeNode node){
if (node==null){ // 终止条件
return;
}
// 当前节点
TreeNode temp=node.left;
node.left=node.right;
node.right=temp;
swapNode(node.left);
swapNode(node.right);
}
}
总结:利用递归法首先要思考递归函数的作用,在整个过程中重复的操作有哪些,将这些重复操作抽取成一个函数。然后再考虑递归的终止条件,当前节点的处理,递归调用自身。
2. 对称二叉树
题目链接:101. - 力扣(LeetCode)
思路:先判断当前两个节点是否相等,再判断左左右右和左右右左的情况。注意两个节点值相等还需要进一步递归判断。
方法:
class Solution {
public boolean isSymmetric(TreeNode root) {
if (root==null){
return true;
}
return both(root.left,root.right);
}
// 判断两个节点的外侧节点和内侧节点是否对称
public boolean both(TreeNode left,TreeNode right){
if (left==null&&right==null){
return true;
}
if (left!=null&&right==null){
return false;
}
if (left==null&&right!=null){
return false;
}
if (left.val!=right.val){
return false;
}
// 两个结点都不为空且值相等,需要进一步判断
return both(left.left,right.right)&&both(left.right,right.left); // 子树的外侧和里侧都要对称
}
}
相似题目:
思路:和对称二叉树思路类似,先判断当前两个节点是否相等,如果值相等再递归判断左左和右右的情况
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p==null&&q==null){
return true;
}
if (p!=null&&q==null){
return false;
}
if (p==null&&q!=null){
return false;
}
if (p.val!=q.val){
return false;
}
return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
}
}
思路:首先判断当前子树是否和模式树相等,再判断左子树和右子树是否和模式串分别相等
class Solution {
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if (isSameTree(root,subRoot)){
return true;
}
boolean left=false;
boolean right=false;
if (root.left!=null){
left=isSubtree(root.left,subRoot);
}
if (root.right!=null){
right=isSubtree(root.right,subRoot);
}
return left||right;
}
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p==null&&q==null){
return true;
}
if (p!=null&&q==null){
return false;
}
if (p==null&&q!=null){
return false;
}
if (p.val!=q.val){
return false;
}
return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
}
}
总结:迭中迭,迭麻了
3. 求最大深度
题目链接:101. - 力扣(LeetCode)
思路:可以用层序迭代遍历判断循环的次数。也可以使用递归函数求传入结点的高度,当前节点的高度是左右子树的高度最大值再加1,叶子节点的高度为0
方法:
class Solution {
public int maxDepth(TreeNode root) {
return maxHeight(root);
}
public int maxHeight(TreeNode root) {
if (root==null){ // 叶子节点高度为0
return 0;
}
// 左右子树的高度最大值再加1
return Math.max(maxHeight(root.left),maxHeight(root.right))+1;
}
}
总结:高度是叶子节点到根节点的长度,从下往上;深度是根节点到根节点的长度,从上往下。
叶子节点到根节点的高度和深度相等
相似题目:
思路:求子树的高度最大值再加1
总结:三元运算符不如Math.max高效,用?:会超出时间限制
4. 求最小深度
题目链接:111. - 力扣(LeetCode)
思路:可以用层序迭代遍历;用递归时仍然是求叶子节点的高度来代替深度。注意深度是根节点到叶子节点的距离,所以要额外处理根节点的左右子树为空的情况
方法:
class Solution {
public int minDepth(TreeNode root) {
// 叶子节点
if (root==null){
return 0;
}
// 左子树为空
if (root.left==null&&root.right!=null){
return 1+minDepth(root.right);
}
// 右子树为空
if (root.right==null&&root.left!=null){
return 1+minDepth(root.left);
}
// 左右子树都不为空
return 1+Math.min(minDepth(root.right),minDepth(root.left));
}
}