面试题1
题目
1.检查两颗树是否相同
1.给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同,如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的
来源:力扣
链接:https://leetcode.cn/problems/same-tree/
![](https://i-blog.csdnimg.cn/blog_migrate/c5b04f8510c285ccb42d521673afc1c7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8e62a8ffaa6ad907b31b86a10b517e21.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9a1c5f9a5779d2bb10b4db599e0b7a99.png)
思路
1.情况一:p为空,q不为空,或者,p不为空,q为空 直接返回false
2.情况二:如果p、q都为空 直接返回true
3.情况三:此时就剩下p、q都不为空,判断p.val == q.val;不相等返回false
然后递归左子树和右子树,当所有的节点判断为true的时候就返回true
代码实现
/**
* 1.题目:
* 给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
* 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
* 时间复杂度O(min(m,n)) m和n分别是p和q的节点数
* 空间复杂度O(min(x,y)) x和y分别是p和q的高度 最坏的情况是O(min(m,n))所有节点在一颗子树上。
*/
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p == null && q != null || p != null && q == null ){
return false;
}
// 走到这里要么都是空,要么都不为空
if(p == null && q == null){
return true;
}
// 都不为空,根节点值不相等,返回false
if(p.val != q.val){
return false;
}
// 都不为空,根节点值相等,判断此根节点的左右子树是否相等
return(isSameTree(p.left,q.left)&&isSameTree(p.right,q.right));
}
![](https://i-blog.csdnimg.cn/blog_migrate/924f52b7912aa30db963e4e137ffad6e.png)
时间复杂度和空间复杂度
时间复杂度O(min(m,n)) m和n分别是p和q的节点数
空间复杂度O(min(x,y)) x和y分别是p和q的高度 最坏的情况是O(min(m,n))所有节点在一颗子树上。
面试题2
题目
2.另一颗树的子树
给你两棵二叉树 root 和 subRoot ,检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true;否则,返回 false 。二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/subtree-of-another-tree
![](https://i-blog.csdnimg.cn/blog_migrate/97a944db93c29647d15fc0734640a543.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d92e06ca3b3ef8ca09b645198a043732.png)
思路
判断是否是相同的树 是返回true
如果不是相同的树,那么进行判断root的左子树和右子树是否与subRoot相同
注意:要提前判断两颗树是否为空
原因:
![](https://i-blog.csdnimg.cn/blog_migrate/afa367cd31a787a63f0db4ff06b95d66.png)
代码实现
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
// 两个都不能为空,因为如果一个为空,另一个不为空,会导致判断是相同树方法返回false,就不会进入第一步,返回不了false,就会进入第二步,产生空指针异常。
if(root == null || subRoot == null){
return false;
}
// 1.判断是否是相同的树,相同返回true
if(isSameTree(root, subRoot)){
return true;
}
// 2.不是相同的树,判断subRoot是否是root的左子树或者右子树
if(isSubtree(root.left, subRoot)){
return true;
}
if(isSubtree(root.right, subRoot)){
return true;
}
return false;
}
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p == null && q != null || p != null && q == null ){
return false;
}
// 走到这里要么都是空,要么都不为空
if(p == null && q == null){
return true;
}
// 都不为空,根节点值不相等,返回false
if(p.val != q.val){
return false;
}
// 都不为空,根节点值相等,判断此根节点的左右子树是否相等
return(isSameTree(p.left,q.left)&&isSameTree(p.right,q.right));
}
![](https://i-blog.csdnimg.cn/blog_migrate/8b810605d495e832acd00449852741e8.png)
时间复杂度和空间复杂度
时间复杂度O(m*n) m和n分别是root的节点数和subRoot的节点数:因为root的节点都要和subRoot的节点进行匹配
空间复杂度O(max(x,y)) x 和 y分别是root的深度和subRoot的深度,最坏是O(m)
面试题3
题目
3.翻转二叉树
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/invert-binary-tree/
![](https://i-blog.csdnimg.cn/blog_migrate/ffd311d88661bfad362b22fef1ea4555.png)
思路
root为空就返回null
只有根节点,返回root
定义临时节点,存放右子树节点,然后交换左右节点,左后将右节点指向临时节点
代码实现
public TreeNode invertTree(TreeNode root) {
//1.判断是否为空
if(root == null){
return null;
}
// 2只有一个节点直接返回根节点
if(root.left==null&&root.right==null){
return root;
}
//3.翻转
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
//4.翻转左右树
invertTree(root.left);
invertTree(root.right);
return root;
}
![](https://i-blog.csdnimg.cn/blog_migrate/58e5ab130e4e124a4cecf44be9b105d0.png)
时间复杂度和空间复杂度
时间复杂度:O(N)
空间复杂度:O(height)
面试题4
题目
4.判断一颗二叉树是否是平衡二叉树。
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/balanced-binary-tree/submissions/
![](https://i-blog.csdnimg.cn/blog_migrate/8c2312930c462538c7371e70268fb7c5.png)
思路一
如果root为null,返回null
求左子树的高度和右子树的高度
高度差的绝对值小于2,同时所有的左子树和右子树都要满足
代码实现1
public int getHeight(TreeNode root){
if (root == null){
return 0;
}
if(root.left == null && root.right == null){
return 1;
}
int leftHeight = getHeight(root.left);
int rightHeight = getHeight(root.right);
return Math.max(leftHeight,rightHeight)+1;
}
public boolean isBalanced(TreeNode root){
if (root == null){
return true;
}
if(root.left == null && root.right == null){
return true;
}
int leftHeight = getHeight(root.left);
int rightHeight = getHeight(root.right);
return Math.abs(leftHeight-rightHeight)<2 && isBalanced(root.left)&&isBalanced(root.right);
}
![](https://i-blog.csdnimg.cn/blog_migrate/8f4ea1030cf500ba046f54234575020c.png)
时间复杂度和空间复杂度
时间复杂度:O(N*2) 遍历每个节点,且每个节点都要算高度
空间复杂度:O(height)
思考
如何实现时间复杂度为O(N)?
![](https://i-blog.csdnimg.cn/blog_migrate/c276308926db14e4590c5dbec9a0d564.png)
思路2
在计算高度的同时就进行判断是否平衡
整体就是,将求高度的方法进行修改,平衡的返回节点的高度,不满足条件的就返回负数-1
判断root是否为空,为空则返回0
判断左右子树的高度是否为小于0,其中有一个小于0就表示是不平衡的,return -1
为正数,判断高度差的绝对值是否小于等于2.满足就返回该节点的高度值,不满足就返回-1
代码实现2
class Solution {
public boolean isBalanced(TreeNode root) {
// 判断是否为正数,是正数就代表平衡
return getBalancedHeight(root) >= 0;
}
public int getBalancedHeight(TreeNode root){
if (root == null){
return 0;
}
// 判断左右子树的是否为负数,如果其中一个的子树为负数就返回为-1,不进行高度的计算。
int leftHeight = getBalancedHeight(root.left);
if(leftHeight<0){
return -1;
}
int rightHeight = getBalancedHeight(root.right);
if(rightHeight<0){
return -1;
}
// 都为正数,判断高度差的绝对值是否小于等于2.
if(Math.abs(leftHeight-rightHeight)<2){
return Math.max(leftHeight,rightHeight)+1;
}else{
return -1;
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/763e835c75a17ed522d7f10e39b6f556.png)
时间复杂度和空间复杂度
时间复杂度:O(N) 遍历每个节点一次
空间复杂度:O(height)
面试题5
题目
5.对称二叉树
给你一个二叉树的根节点 root , 检查它是否轴对称。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/symmetric-tree/
![](https://i-blog.csdnimg.cn/blog_migrate/9dae722547e3b13096e5788f5c327005.png)
思路
1.其实就是检查左子树和右子树是否是对称的
函数:public boolean isSymmetricChild(TreeNode rootLeft,TreeNode rootRight)
左子树为空,同时右子树不为空 或者 左子树不为空,同时右子树为空 都是不对称
左子树为空,右子树也为空 是对称的
此时左右子树都是不为空的,这时候判断左子树的val值和右子树的val值是否相等,不想等直接返回false
最后必须满足左子树的左树和右子树的右树相等以及左子树的右侧树和右子树的左树相等
2.此时判断了左子树和右子树是否对称
在到原来的函数进行判断
函数:public boolean isSymmetric(TreeNode root)
首先root==null return false
只有root一个节点就返回true
返回左子树和右子树是否相等的结果
代码实现
class Solution {
public boolean isSymmetric(TreeNode root){
if (root == null){
return false;
}
if (root.left == null && root.right == null){
return true;
}
return isSymmetricChild(root.left,root.right);
}
public boolean isSymmetricChild(TreeNode rootLeft,TreeNode rootRight){
if(rootLeft == null && rootRight != null || rootLeft != null && rootRight == null){
return false;
}
if(rootLeft == null && rootRight == null){
return true;
}
if(rootLeft.val != rootRight.val){
return false;
}
return isSymmetricChild(rootLeft.left, rootRight.right) && isSymmetricChild(rootLeft.right, rootRight.left);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/cf67bf4369c4af557d24a4db19c5a87b.png)
时间复杂度和空间复杂度
* 时间复杂度:O(N)
* 空间复杂度:O(height)
面试题6
题目
6.分层遍历
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/
![](https://i-blog.csdnimg.cn/blog_migrate/beb3bf76f501d4debaf56fba153b614c.png)
思路
使用队列的思想进行实现,因为队列是先进先出
创建一个队列用来层序遍历
根据队列的长度进行进队列和出队列
每一次循环(循环结束的条件是队列为空)就创建一个顺序表level,用来添加层级元素
将出队列的添加到顺序表level
将顺序表添加到总的顺序表list里
![](https://i-blog.csdnimg.cn/blog_migrate/c9645e9110d019e369d6cab111476591.png)
![](https://i-blog.csdnimg.cn/blog_migrate/54b238a966164c23bf6d406c65a53a8a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a2526e96929d881b94b68b63aca872a2.png)
代码实现
class Solution {
public List<List<Integer>> levelOrder(TreeNode root){
List<List<Integer>> list = new ArrayList<>();
if (root == null){
return list;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
List<Integer> level = new ArrayList<>();
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode cur = queue.poll();
level.add(cur.val);
if(cur.left != null){
queue.offer(cur.left);
}
if(cur.right != null){
queue.offer(cur.right);
}
}
list.add(level);
}
return list;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/93a469f13086c7c80aa4574efd2fc19f.png)
时间复杂度和空间复杂度
* 时间复杂度:O(N)
* 空间复杂度:O(height)