187 lines
7.0 KiB
Markdown
187 lines
7.0 KiB
Markdown
|
||
<p align="center">
|
||
<a href="https://mp.weixin.qq.com/s/RsdcQ9umo09R6cfnwXZlrQ"><img src="https://img.shields.io/badge/PDF下载-代码随想录-blueviolet" alt=""></a>
|
||
<a href="https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw"><img src="https://img.shields.io/badge/刷题-微信群-green" alt=""></a>
|
||
<a href="https://space.bilibili.com/525438321"><img src="https://img.shields.io/badge/B站-代码随想录-orange" alt=""></a>
|
||
<a href="https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ"><img src="https://img.shields.io/badge/知识星球-代码随想录-blue" alt=""></a>
|
||
</p>
|
||
<p align="center"><strong>欢迎大家<a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
|
||
|
||
|
||
# 100. 相同的树
|
||
|
||
题目地址:https://leetcode-cn.com/problems/same-tree/
|
||
|
||
给定两个二叉树,编写一个函数来检验它们是否相同。
|
||
|
||
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
|
||
|
||

|
||
|
||

|
||
|
||
|
||
# 思路
|
||
|
||
在[101.对称二叉树](https://mp.weixin.qq.com/s/Kgf0gjvlDlNDfKIH2b1Oxg)中,我们讲到对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,理解这一点就知道了**其实我们要比较的是两个树(这两个树是根节点的左右子树)**,所以在递归遍历的过程中,也是要同时遍历两棵树。
|
||
|
||
理解这一本质之后,就会发现,求二叉树是否对称,和求二叉树是否相同几乎是同一道题目。
|
||
|
||
**如果没有读过[二叉树:我对称么?](https://mp.weixin.qq.com/s/Kgf0gjvlDlNDfKIH2b1Oxg)这一篇,请认真读完再做这道题,就会有感觉了。**
|
||
|
||
递归三部曲中:
|
||
|
||
1. 确定递归函数的参数和返回值
|
||
|
||
我们要比较的是两个树是否是相互相同的,参数也就是两个树的根节点。
|
||
|
||
返回值自然是bool类型。
|
||
|
||
代码如下:
|
||
```
|
||
bool compare(TreeNode* tree1, TreeNode* tree2)
|
||
```
|
||
|
||
分析过程同[101.对称二叉树](https://mp.weixin.qq.com/s/Kgf0gjvlDlNDfKIH2b1Oxg)。
|
||
|
||
2. 确定终止条件
|
||
|
||
**要比较两个节点数值相不相同,首先要把两个节点为空的情况弄清楚!否则后面比较数值的时候就会操作空指针了。**
|
||
|
||
节点为空的情况有:
|
||
|
||
* tree1为空,tree2不为空,不对称,return false
|
||
* tree1不为空,tree2为空,不对称 return false
|
||
* tree1,tree2都为空,对称,返回true
|
||
|
||
此时已经排除掉了节点为空的情况,那么剩下的就是tree1和tree2不为空的时候:
|
||
|
||
* tree1、tree2都不为空,比较节点数值,不相同就return false
|
||
|
||
此时tree1、tree2节点不为空,且数值也不相同的情况我们也处理了。
|
||
|
||
代码如下:
|
||
```C++
|
||
if (tree1 == NULL && tree2 != NULL) return false;
|
||
else if (tree1 != NULL && tree2 == NULL) return false;
|
||
else if (tree1 == NULL && tree2 == NULL) return true;
|
||
else if (tree1->val != tree2->val) return false; // 注意这里我没有使用else
|
||
```
|
||
|
||
分析过程同[101.对称二叉树](https://mp.weixin.qq.com/s/Kgf0gjvlDlNDfKIH2b1Oxg)
|
||
|
||
3. 确定单层递归的逻辑
|
||
|
||
* 比较二叉树是否相同 :传入的是tree1的左孩子,tree2的右孩子。
|
||
* 如果左右都相同就返回true ,有一侧不相同就返回false 。
|
||
|
||
代码如下:
|
||
|
||
```C++
|
||
bool left = compare(tree1->left, tree2->left); // 左子树:左、 右子树:左
|
||
bool right = compare(tree1->right, tree2->right); // 左子树:右、 右子树:右
|
||
bool isSame = left && right; // 左子树:中、 右子树:中(逻辑处理)
|
||
return isSame;
|
||
```
|
||
最后递归的C++整体代码如下:
|
||
|
||
```C++
|
||
class Solution {
|
||
public:
|
||
bool compare(TreeNode* tree1, TreeNode* tree2) {
|
||
if (tree1 == NULL && tree2 != NULL) return false;
|
||
else if (tree1 != NULL && tree2 == NULL) return false;
|
||
else if (tree1 == NULL && tree2 == NULL) return true;
|
||
else if (tree1->val != tree2->val) return false; // 注意这里我没有使用else
|
||
|
||
// 此时就是:左右节点都不为空,且数值相同的情况
|
||
// 此时才做递归,做下一层的判断
|
||
bool left = compare(tree1->left, tree2->left); // 左子树:左、 右子树:左
|
||
bool right = compare(tree1->right, tree2->right); // 左子树:右、 右子树:右
|
||
bool isSame = left && right; // 左子树:中、 右子树:中(逻辑处理)
|
||
return isSame;
|
||
|
||
}
|
||
bool isSameTree(TreeNode* p, TreeNode* q) {
|
||
return compare(p, q);
|
||
}
|
||
};
|
||
```
|
||
|
||
|
||
**我给出的代码并不简洁,但是把每一步判断的逻辑都清楚的描绘出来了。**
|
||
|
||
如果上来就看网上各种简洁的代码,看起来真的很简单,但是很多逻辑都掩盖掉了,而题解可能也没有把掩盖掉的逻辑说清楚。
|
||
|
||
**盲目的照着抄,结果就是:发现这是一道“简单题”,稀里糊涂的就过了,但是真正的每一步判断逻辑未必想到清楚。**
|
||
|
||
当然我可以把如上代码整理如下:
|
||
|
||
## 递归
|
||
|
||
```C++
|
||
class Solution {
|
||
public:
|
||
bool compare(TreeNode* left, TreeNode* right) {
|
||
if (left == NULL && right != NULL) return false;
|
||
else if (left != NULL && right == NULL) return false;
|
||
else if (left == NULL && right == NULL) return true;
|
||
else if (left->val != right->val) return false;
|
||
else return compare(left->left, right->left) && compare(left->right, right->right);
|
||
|
||
}
|
||
bool isSameTree(TreeNode* p, TreeNode* q) {
|
||
return compare(p, q);
|
||
}
|
||
};
|
||
```
|
||
|
||
## 迭代法
|
||
|
||
```C++
|
||
lass Solution {
|
||
public:
|
||
|
||
bool isSameTree(TreeNode* p, TreeNode* q) {
|
||
if (p == NULL && q == NULL) return true;
|
||
if (p == NULL || q == NULL) return false;
|
||
queue<TreeNode*> que;
|
||
que.push(p); //
|
||
que.push(q); //
|
||
while (!que.empty()) { //
|
||
TreeNode* leftNode = que.front(); que.pop();
|
||
TreeNode* rightNode = que.front(); que.pop();
|
||
if (!leftNode && !rightNode) { //
|
||
continue;
|
||
}
|
||
//
|
||
if ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) {
|
||
return false;
|
||
}
|
||
que.push(leftNode->left); //
|
||
que.push(rightNode->left); //
|
||
que.push(leftNode->right); //
|
||
que.push(rightNode->right); //
|
||
}
|
||
return true;
|
||
}
|
||
};
|
||
```
|
||
|
||
# 其他语言版本
|
||
|
||
Java:
|
||
|
||
Python:
|
||
|
||
Go:
|
||
|
||
JavaScript:
|
||
|
||
-----------------------
|
||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||
<div align="center"><img src=../pics/公众号.png width=450 alt=> </img></div>
|
||
|