题目:
Given two binary trees, write a function to check if they are the same or not.
Two binary trees are considered the same if they are structurally identical and the nodes have the same value.
Example 1:
Input: 1 1
/ \ / \
2 3 2 3
[1,2,3], [1,2,3]
Output: true
Example 2:
Input: 1 1
/ \
2 2
[1,2], [1,null,2]
Output: false
Example 3:
Input: 1 1
/ \ / \
2 1 1 2
[1,2,1], [1,1,2]
Output: false
这又双叒是一道之前算法课水过的但现在还是不会做的题orz 题目要求很简单,就是判断两棵树是不是一样的。如果要判断两棵树是否相同,那么就从root开始一个个判断它们的数字是否相等。在判断数字是否相等之前还可以判断它们的结构,如果一棵为空、另一棵有子节点,那么它们就必然不相同。可以通过递归来解决这个问题:如果两个节点存在为NULL的,那就返回两个节点是否相同,如果相同则两个都是NULL,为true,否则不同就要返回false,通过这样一句可以减少if-else的使用。如果两个节点不为NULL,那么就需要比较这两个节点的value是否相同,以及以这两个节点为root的子树是否相同,这就是递归的用法了。代码如下,运行时间0ms:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if (!p || !q) {
return (p == q);
}
else {
bool left = isSameTree(p->left, q->left);
bool right = isSameTree(p->right, q->right);
if ((p->val == q->val) && left && right) {
return true;
}
else {
return false;
}
}
}
};
2020.10.06 Java:
会写了。复杂度O(n)。
Runtime: 0 ms, faster than 100.00% of Java online submissions for Same Tree.
Memory Usage: 36.4 MB, less than 91.84% of Java online submissions for Same Tree.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null || q == null) {
return p == q;
}
if (p.val != q.val) {
return false;
} else {
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
}
}
2023.1.2
嗯还是秒写出来了递归,写法和以前略微不同。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
} else if (p == null || q == null) {
return false;
}
return p.val == q.val && isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
}
除此之外,还看到一个非递归的做法,大意就是采用一个stack来存储每一个节点的左、右两个节点,类似于前序遍历。从根节点开始,把两棵树的根节点push进栈,然后从根节点往下,每次pop最后的两个节点出来比较它们是否相同,如果相同,则可以把这个节点的左右子节点push进栈,继续进行比较,直到栈为空,或者pop出来的两个节点的value不同,返回false。代码如下,运行时间0ms:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
stack<TreeNode*> stk;
stk.push(p);
stk.push(q);
while (!stk.empty()) {
TreeNode* first = stk.top();
stk.pop();
TreeNode* second = stk.top();
stk.pop();
if (!first && !second) {
continue;
}
else if (!first || !second || (first->val != second->val)) {
return false;
}
else {
stk.push(first->left);
stk.push(second->left);
stk.push(first->right);
stk.push(second->right);
}
}
return true;
}
};
2020.10.12 Java:
迭代写法感觉有点像dfs/bfs,找一种方式遍历它,我用了两个stack做dfs,每次取出stack top的元素比较它俩value是否相等。在push他们的子节点的时候需要注意,因为java中Deque是不允许存在null节点的(Queue是可以的),所以要先判断左右子节点是否存在,并且如果是一个存在但另一个不存在的话就直接return false,如果两个都不存在的话可以继续往下走。其实好像一个stack也可以做,每次成双成对地往里push,然后pop也是pop两个出来进行比较就可以了。
Runtime: 0 ms, faster than 100.00% of Java online submissions for Same Tree.
Memory Usage: 36.4 MB, less than 15.96% of Java online submissions for Same Tree.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null || q == null) {
return p == q;
}
Deque<TreeNode> stack1 = new ArrayDeque<>();
Deque<TreeNode> stack2 = new ArrayDeque<>();
stack1.push(p);
stack2.push(q);
while (!stack1.isEmpty() && !stack2.isEmpty()) {
TreeNode node1 = stack1.pop();
TreeNode node2 = stack2.pop();
if (node1.val != node2.val) {
return false;
}
if (node1.left != null && node2.left != null) {
stack1.push(node1.left);
stack2.push(node2.left);
} else if (node1.left != node2.left) {
return false;
}
if (node1.right != null && node2.right != null) {
stack1.push(node1.right);
stack2.push(node2.right);
} else if (node1.right != node2.right) {
return false;
}
}
return true;
}
}
2023.1.2
瞄到了之前写的代码知道可以用两个deque来存以后,就轻松写出了代码,和之前一样,只是忘了可以直接比较node1.left != node2.left来判断当node1和node2至少有一个为null时他们一不一样。
然后试了只用一个stack的做法,嗯,其实是完全一样的,代码都不用改多少,其实就是多年前用C++写的那会儿记的那个方法。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null || q == null) {
return p == q;
}
Deque<TreeNode> stack = new ArrayDeque<>();
stack.push(p);
stack.push(q);
while (!stack.isEmpty()) {
TreeNode node1 = stack.pop();
TreeNode node2 = stack.pop();
if (node1.val != node2.val) {
return false;
}
if (node1.left != null && node2.left != null) {
stack.push(node1.left);
stack.push(node2.left);
} else if (node1.left != node2.left) {
return false;
}
if (node1.right != null && node2.right != null) {
stack.push(node1.right);
stack.push(node2.right);
} else if (node1.right != node2.right) {
return false;
}
}
return true;
}
}