一、题示
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
示例 1:
输入: p = [1,2,3], q = [1,2,3]
输出: true
示例 2:
输入: p = [1,2], q = [1,null,2]
输出: false
示例 3:
输入: p = [1,2,1], q = [1,1,2]
输出: false
提示:
- 两棵树上的节点数目都在范围
[0, 100]内 -104 <= Node.val <= 104
二、解题思路
该二叉树采用的是顺序存储结构,用的是一堆数组存储二叉树中的结点,并且结点的存储位置,也就是数组的下标体现了节点之间的逻辑关系
1、将数组转化为字符串直接对比
2、递归思路
3、二叉树可通过前序遍历、中序遍历、后序遍历、层序遍历的方式,在遍历过程中进行比对判断是否相等,如果存在对应的值不等,则跳出遍历,直接返回不相同(false)的结果。
三、代码实现
1、将数组转化为字符串
public boolean isSameTree(TreeNode p, TreeNode q) {
return transform(p).transform(transform(q));
}
public String transform(TreeNode root) {
if(root == null) {
return "#";
}
String left = transform(root.left);
String right = transform(root.right);
return left+","+root.val+","+right;
}
2、递归实现
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) return true;
if (p == null) return false;
if (q == null) return false;
if (p.val == q.val) {
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
} else {
return false;
}
}
3、前序遍历判断
public boolean isSameTreePre(TreeNode p, TreeNode q) {
if (p == null && q == null) return true;
if (p == null) return false;
if (q == null) return false;
Stack<TreeNode> stackP = new Stack<>();
stackP.add(p);
Stack<TreeNode> stackQ = new Stack<>();
stackQ.add(q);
while (!stackP.isEmpty() || !stackQ.isEmpty()) {
TreeNode pNode = stackP.pop();
TreeNode qNode = stackQ.pop();
if (pNode == null && qNode == null) continue;
if (pNode == null) return false;
if (qNode == null) return false;
if (pNode.val != qNode.val) {
return false;
} else {
stackP.add(pNode.right);
stackQ.add(qNode.right);
stackP.add(pNode.left);
stackQ.add(qNode.left);
}
}
return true;
}
4、中序遍历判断
public boolean isSameTreeMid(TreeNode p, TreeNode q) {
if (p == null && q == null) return true;
if (p == null) return false;
if (q == null) return false;
Stack<TreeNode> stackP = new Stack<>();
Stack<TreeNode> stackQ = new Stack<>();
while (p != null || q != null || !stackP.isEmpty() || !stackQ.isEmpty()) {
if (p != null && q != null) {
stackP.add(p);
stackQ.add(q);
p = p.left;
q = q.left;
} else if (q == null && p == null) {
p = stackP.pop();
q = stackQ.pop();
if (p.val != q.val) {
return false;
}
p = p.right;
q = q.right;
} else {
return false;
}
}
return true;
}
5、后序遍历判断(双栈)
public boolean isSameTreeEnd1(TreeNode p, TreeNode q) {
if (p == null && q == null) return true;
if (p == null) return false;
if (q == null) return false;
Stack<TreeNode> stackP = new Stack<>();
Stack<TreeNode> stackPTmp = new Stack<>();
Stack<TreeNode> stackQ = new Stack<>();
Stack<TreeNode> stackQTmp = new Stack<>();
while (p != null || q != null || !stackPTmp.isEmpty() || !stackQTmp.isEmpty()) {
if (p != null && q != null) {
stackP.add(p);
stackPTmp.add(p);
stackQ.add(q);
stackQTmp.add(p);
p = p.right;
q = q.right;
} else if (p == null && q == null) {
p = stackPTmp.pop();
p = p.left;
q = stackQTmp.pop();
q = q.left;
} else {
return false;
}
}
while (!stackP.isEmpty() && !stackQ.isEmpty()) {
if (stackP.pop().val != stackQ.pop().val) {
return false;
}
}
return true;
}
6、后序遍历判断(单栈)
public boolean isSameTreeEnd2(TreeNode p, TreeNode q) {
if (p == null && q == null) return true;
if (p == null) return false;
if (q == null) return false;
Stack<TreeNode> stackP = new Stack<>();
stackP.add(p);
TreeNode pPre = null;
Stack<TreeNode> stackQ = new Stack<>();
stackQ.add(q);
TreeNode qPre = null;
while (!stackP.isEmpty() || !stackQ.isEmpty()) {
p = stackP.peek();
q = stackQ.peek();
if (((pPre != null && (p.left == pPre || p.right == pPre)) || (p.left == null && p.right == null)) &&
((qPre != null && (q.left == qPre || q.right == qPre)) || (q.left == null && q.right == null))) {
if (p.val != q.val) {
return false;
}
pPre = p;
qPre = q;
stackP.pop();
stackQ.pop();
} else {
if (p.right != null && q.right != null) {
stackP.add(p.right);
stackQ.add(q.right);
} else if (p.right != null || q.right != null) {
return false;
}
if (p.left != null && q.left != null) {
stackP.add(p.left);
stackQ.add(q.left);
} else if (p.left != null || q.left != null) {
return false;
}
}
}
return true;
}