题目01 - 判断二叉树是否对称相等
原题链接
题目描述
你一个二叉树的根节点 root , 检查它是否轴对称
输入示例
思路 01 - 递归
1. 比较的节点
- 比较的是两个子树的里侧和外侧的元素是否相等
- 假设当前比较的节点为 node。其左右子节点已经对称相等
node.left.val = node.right.val
- 第一组: 比较里侧为
node.left.left&&node.right.right - 第二组: 比较外侧为
node.left.right&&node.right.left
2. 递归终止条件:
- 左不为空,右为空,不对称返回
false - 左右都为空,对称,返回
true - 左右都不为空,比较节点的数值,不相同就返回 false
- 判断当前组节点是否对称相等的条件
- 比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子
- 比较内侧是否对称:传入左节点的右孩子和右节点的左孩子
- 后续如果左右都对称就返回
true, 有一侧不对称就返回 false
代码实现 - 递归
class Solution {
public boolean isSymmetric(TreeNode root) {
// 如果根节点为空或者仅有一个节点
if (root == null || (root.left == null && root.right == null))
return true;
return isSymmetricHelper(root.left, root.right);
}
//递归判断是否对称
public boolean isSymmetricHelper(TreeNode left, TreeNode right) {
if (left == null && right == null) {
return true;
}
if (left == null || right == null) {
return false;
}
if (left.val != right.val) {
return false;
}
// 比较外侧里侧是否对称
return isSymmetricHelper(left.left, right.right) && isSymmetricHelper(left.right, right.left);
}
}
执行结果
- 时间复杂度:
O(N),其中 n 是二叉树的节点数。 - 空间复杂度:
O(H),其中 h 是二叉树的高度。最坏情况下为 O(n),最佳情况下为 O(log n)。
思路 02 - 迭代
- 参考层序遍历的思想;借助队列遍历
- 循环判断条件,只要队内不为空
- 但是入队顺序不同
- 首轮将当前节点的左右子节点入队
- 每次出队需要连续将两个节点出队
- 判断如果对称相等后按照如下如何入队:
- 左子树左子节点 和 右子树右子节点 为一组 (外侧)
- 左子树的右子节点 和 右子树的左子节点为一组 (里侧)
- 判断是否对称的条件
- 如果出队的两个节点都为 null; 则对称相等,继续出队 (continue)
- 如果两个节点仅有一个为 null; 则不是对称相等,返回 false;
- 如果两个节点都不为 null; 则判断两个节点值是否相等,相等则对称相等;否则不对称相等
示意图
- 蓝色节点代表还未入队
- 橙色节点表示已经入队
代码实现
class Solution {
public boolean isSymmetric(TreeNode root) {
// 检查输入
if (null == root || root.left == null && root.right == null)
return true;
Deque<TreeNode> queue = new LinkedList<>();
// 首轮入队
queue.offer(root.left);
queue.offer(root.right);
// 循环
while (!queue.isEmpty()) {
TreeNode peek1 = queue.poll();
TreeNode peek2 = queue.poll();
// 都为空
if (peek1 == null && peek2 == null) {
continue;
}
// 其中一个为空
if (peek1 == null || peek2 == null) {
return false;
}
// 都不为空
if (peek1.val != peek2.val) {
return false;
}
// 将外侧组节点入队
queue.offer(peek1.left);
queue.offer(peek2.right);
// 将里侧组节点入队
queue.offer(peek1.right);
queue.offer(peek2.left);
}
// 全部对称相等则满足
return true;
}
}
执行结果
- 时间复杂度:
O(N) - 空间复杂度:
O(N)
题目 02 - 相同的树
原题链接
题目描述
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
输入示例
思路
- 递归返回条件
- 如果节点 p 和 q 都为空,返回 true
- 如果仅有其中一个节点为空,不相等,返回 false
- 如果都不为空但是 val 不相等,返回 false
- 如果都不为空并且 val 一致,继续比较两个分组:
- p 的左子树和 q 的右子树
- p 的右子树和 q 的右子树
- 如果后续比较存在一次不相等则判定不是相等二叉树
代码实现
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
//递归终止条件一:两个节点都为空,两个节点相等
if (null == p && null == q) {
return true;
}
//递归终止条件二: 仅有一个节点为空,两节点不相等
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);
}
}
执行结果
- 时间复杂度:
O(1) - 空间复杂度:
O(1)
题目 03 - 另外一颗子树
原题链接
题目描述
给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。
二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。
输入示例
思路
- 递归遍历root下的所有节点,与 subTree 比较;比较二叉树是否相等的逻辑与
LeetCode 100 - 判断二叉树是否相等一致 - 递归返回条件一:如果
root为空,返回false;说明沿着当前树枝往下不存在相同子树 - 递归返回条件二: 如果
root和subTree相等,返回true;当前root节点下的子树与subTree一致 - 递归查找
root.left子树是否存在和subTree一致的子树 ||root.right子树是否存在和subTree一致的子树
代码实现
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
// 检查输入
if (root == null) {
return false;
}
// 递归遍历root各个节点是子树根节点
if (isSameTree(root, subRoot)) {
return true;
}
// 递归左、右子节点
return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);
}
public boolean isSameTree(TreeNode root, TreeNode subTree) {
// 节点都为空
if (root == null && subTree == null) {
return true;
}
// 仅有一个节点为空
if (root == null || subTree == null) {
return false;
}
// 节点元素不相等
if (root.val != subTree.val) {
return false;
}
return isSameTree(root.left, subTree.left) && isSameTree(root.right, subTree.right);
}
执行结果
- 时间复杂度:
O(N) - 空间复杂度:
O(H)