BM31 对称的二叉树
描述
给定一棵二叉树,判断其是否是自身的镜像(即:是否对称)
例如: 下面这棵二叉树是对称的
下面这棵二叉树不对称。
数据范围:节点数满足 ,节点上的值满足
要求:空间复杂度
,时间复杂度
备注:你可以用递归和迭代两种方法解决这个问题
示例1
输入:
{1,2,2,3,4,4,3}
复制返回值:
true
复制
示例2
输入:
{8,6,9,5,7,7,5}
复制返回值:
false
题解
递归解法
判断一颗二叉树是否为镜像二叉树,可以通过判断2个二叉树是否相互镜像来实现。假设有2个二叉树,t1和t2,那么只有t1和t2节点的值相等,且他们的左子树和右子数相互镜像时,这两颗二叉树才相互镜像,基本思路如下:
- 1:两种方向的前序遍历,同步过程中的当前两个节点,同为空,属于对称的范畴。
- 2:当前两个节点只有一个为空或者节点值不相等,已经不是对称的二叉树了。
- 3:第一个节点的左子树与第二个节点的右子树同步递归对比,第一个节点的右子树与第二个节点的左子树同步递归比较。
// https://www.nowcoder.com/practice/ff05d44dfdb04e1d83bdbdab320efbcb?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj
struct TreeNode
{
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
bool recursion(TreeNode *root1, TreeNode *root2)
{
//可以两个都为空
if (root1 == NULL && root2 == NULL)
return true;
//只有一个为空或者节点值不同,必定不对称
if (root1 == NULL || root2 == NULL || root1->val != root2->val)
return false;
//每层对应的节点进入递归
return recursion(root1->left, root2->right) && recursion(root1->right, root2->left);
}
bool isSymmetrical_r(TreeNode *pRoot)
{
return recursion(pRoot, pRoot);
}
非递归解法
非递归的解法借鉴了二叉树的层次遍历,只是稍微有一些变形。普通层次遍历的时候我们将空节点跳过了,但是为了判断二叉树的节点是否对称,我们需要将空节点进行补位。
注意:
不管当前节点的左右节点是否为空,都应该放入队列,前提条件是当前节点本身不为空。
bool isSymmetrical(TreeNode *root)
{
if (root == nullptr)
{
return true;
}
std::queue<TreeNode *> q;
q.push(root);
while (!q.empty())
{
int n = q.size();
std::vector<TreeNode *> v;
while (n-- > 0)
{
auto node = q.front();
v.push_back(node);
q.pop();
if (node != nullptr)
{
q.push(node->left);
q.push(node->right);
}
}
for (int i = 0; i < v.size() / 2; ++i)
{
if (v[i] == nullptr && v[v.size() - 1 - i] == nullptr)
{
continue;
}
if (v[i] != nullptr && v[v.size() - 1 - i] == nullptr)
{
return false;
}
if (v[i] == nullptr && v[v.size() - 1 - i] != nullptr)
{
return false;
}
if (v[i]->val != v[v.size() - 1 - i]->val)
{
return false;
}
}
}
return true;
}