文章目录
- 前言
- 1. 翻转二叉树
- 1.1 题目
- 1.2 解题思路
- 1.3 代码实现
- 1.4 时空复杂度
- 2. 对称二叉树
- 2.1 题目
- 2.2 解题思路
- 2.3 代码实现
- 2.4 时空复杂度
- 3. 平衡二叉树
- 3.1 题目
- 3.2 解题思路
- 3.3 代码实现
- 3.4 时空复杂度
- 结语
前言
本篇博客主要介绍二叉树的经典 OJ 题,题目主要来源于力扣和牛客网,熟练掌握这些题型将会使你对二叉树的理解更上一层楼
1. 翻转二叉树
原题地址:力扣 226.翻转二叉树
1.1 题目
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点
1.2 解题思路
看到是二叉树,我们就要考虑能不能使用递归法(大部分情况下是可以的)。在本题中,题目要求我们翻转二叉树,意思也就是以根节点为基准,交换左右子树(示例2),而且子树也同理(示例1),我们需要递归的交换左右子树,达到翻转二叉树的效果,最后返回根节点
根据思路我们可以总结出递归的两个条件:
-
终止条件
当前节点为 null 就返回
-
单层递归的逻辑
交换当前节点的左右节点,再递归的交换当前节点的左节点,递归的交换当前节点的右节点
1.3 代码实现
class Solution {public TreeNode invertTree(TreeNode root) {//终止条件if(root == null) {return null;}//暂时存储左节点,让左右节点交换TreeNode tmp = root.left;root.left = root.right;root.right = tmp;//交换结束,递归左节点invertTree(root.left);//递归右节点invertTree(root.right);//最后返回根节点return root;}
}
1.4 时空复杂度
时间复杂度为 O(N),每个节点都会遍历到
空间复杂度为 O(N),最坏情况下树形成链状
2. 对称二叉树
原题链接:力扣 101.对称二叉树
2.1 题目
给你一个二叉树的根节点 root , 检查它是否轴对称
2.2 解题思路
题目要求我们判断一棵二叉树是否轴对称,通过示例我们可以看出,轴对称是以根节点为基准的,也就是说,子树我们就不要求轴对称(要跟前一道题做区分)。就像示例 1,我们需要比较的是左子树的右子树跟右子树的左子树是否相等
在这里我们还是使用递归法:
-
终止条件
首先要判断两个节点是否为空:
- 左节点为空,右节点也为空,返回 true
- 左节点为空,右节点不为空,返回 false
- 左节点不为空,右节点为空,返回 false
此时排除了节点为空的情况,可以来判断节点里的值是否相等了:
- 相等返回 true,不相等返回 false
-
单层递归的逻辑
此时就要来往下递归,传入左节点的右孩子跟右节点的左孩子,再 与(&&) 上传入左节点的左孩子和右节点的右孩子,如果左右堆成就返回 true,有一侧不对称就返回 false
2.3 代码实现
class Solution {public boolean isSymmetric(TreeNode root) {//先把根节点为null的情况排除掉if(root == null) {return true;}//传入根节点的左右子树return isSymmetricChild(root.left, root.right);}public boolean isSymmetricChild(TreeNode leftTree, TreeNode rightTree) {//都为null,则返回trueif(leftTree == null && rightTree == null) {return true;}//因为上面排除了都为null的情况,所以这里只要有一个是null,就返回falseif(leftTree == null || rightTree == null) {return false;}//都不为null,开始判断里面的值if(leftTree.val != rightTree.val) {return false;}//开始递归传入左子树的右节点和右子树的左节点//以及左子树的左节点和右子树的右节点,同为true就返回true,否则就只能返回falsereturn isSymmetricChild(leftTree.left,rightTree.right) && isSymmetricChild(leftTree.right,rightTree.left);}
}
2.4 时空复杂度
时间复杂度为 O(N),每次递归都可以判断一对节点是否堆成,因此最多调用 N / 2 次
空间复杂度最差情况下也是 O(N)
3. 平衡二叉树
原题链接:力扣 110.平衡二叉树
3.1 题目
给定一个二叉树,判断它是否是平衡二叉树
平衡二叉树 是指该树所有节点的左右子树的深度相差不超过 1
3.2 解题思路
在力扣的题目中,默认根节点的深度是 1。要求该树所有节点的左右子树深度相差不超过 1,也就是小于等于 1,那我们就得去遍历,至于是哪种遍历,我们要根据题目需求,它让我们求高度还是求深度
求高度使用后序遍历:因为后序遍历是左右根(LRN),因此父节点可以根据左右节点返回上来的高度数再加一,层层向上,得到树的高度
求深度使用前序遍历:因为前序遍历是根左右(NLR),它能一直向下遍历,而不是向上去返回结果,求得深度
在本题中,我们要求的是深度,做后序遍历可以从底至顶返回子树深度,当前树的深度等于左子树的深度与右子树的深度中的最大值 +1。还是经典的递归:
-
终止条件
遇到空节点就终止,返回 0,表示此时以该节点为根节点的树的高度为 0
-
单层递归的逻辑
我们要比较左子树高度和其右子树高度的差值。分别求出其左右子树的高度,然后如果差值小于等于1,则返回 true,否则返回 false,表示已经不是二叉平衡树
3.3 代码实现
class Solution {public boolean isBalanced(TreeNode root) {//先判断根节点是否为null的情况if (root == null) {//是就返回truereturn true;}//求左子树的深度int leftH = getHeight(root.left);//求右子树的深度int rightH = getHeight(root.right);//相减的绝对值小于1,则表示以该节点为根节点的树平衡,返回true,再与上该节点的左子树和右子树return Math.abs(leftH - rightH) <= 1&& isBalanced(root.left)&& isBalanced(root.right);}//求树的深度public int getHeight(TreeNode root) {if (root == null) {return 0;}//往下一直递归int leftHeight = getHeight(root.left);int rightHeight = getHeight(root.right);//返回左右子树的深度的最大值,还要加一return leftHeight > rightHeight ?leftHeight+1 : rightHeight+1;}
}
3.4 时空复杂度
时间复杂度为 O(N),最差情况下要遍历所有节点
空间复杂度为 O(N),最差情况下,树退化成链表,递归需要使用 O(N) 的栈空间
结语
这几道题我在一两个月前就已经做过的题,现在回来重新写一遍还是有点吃力。想写成博客,把做题思路顺畅地写出来还是很难。而且二叉树的很多题用递归写很方便,就是不好讲,讲了也不一定能看懂😣请见谅
主要还是因为博主太菜了,力扣的题也刷的很少。大家在刷题的时候没思路可以看看评论区大佬的讲解,懂了后再去自己敲一遍。博主这种菜鸟就是这样做的,虽然提升有点慢,但也多多少少吸收点做题经验
新手刷题常常会出现明明之前看题解后做过,过段时间再回来还是一点做不出来,正常(我的现状😭),只能多刷几遍,共勉吧家人们
希望大家能喜欢这篇文章,有总结不到位的地方还请多多谅解,若有出现纰漏,希望大佬们看到错误之后能够在私信或评论区指正,博主会及时改正,共同进步!