题目:请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。例如下图中,第一棵二叉树是对称的,另外两棵不是。
思路:
这道题我开始想的是,先求出二叉树的镜像然后进行对比,比较两棵二叉树是否相同。理论上是可行的,但是过程会繁琐一点。书中给了一种思路:先对二叉树进行前序遍历,比如上面第一棵二叉树前序序列为8657675,再自定义一种前序遍历的方式,每次遍历一个节点之后,先遍历一个节点的右节点,再遍历节点的左节点。比如上面第一棵树的自定义前序序列为8657675,两个序列一样说明,这个二叉树为对称二叉树。但是再看看第三棵树,发现两种遍历的序列都是777777,但是这棵树不是对称的二叉树,那么怎么解决这个问题呢?可以把所有的叶子节点处都补上缺失的左右孩子(nullptr),这样再对第三棵树进行前序遍历的结果就是{7 7 7 nullptr nullptr 7 nullptr nullptr 7 7 nullptr nullptr nullptr};自定义前序遍历的结果为{7 7 nullptr 7 nullptr nullptr 7 7 nullptr nullptr 7 nullptr nullptr},可以看出来这两个序列是不相等的。下面代码的函数重载操作很有意思,这样就可以实现两个序列同步的遍历和比较。还是老问题,要注意输入的节点为空等问题,保证代码的鲁棒性。
代码:
struct BinaryTreeNode
{
double m_dbValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
bool isSymmetrical(BinaryTreeNode* pRoot)//函数重载
{
return isSymmetrical(pRoot, pRoot);
}
bool isSymmetrical(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
if (pRoot1 == nullptr&&pRoot2 == nullptr)
return true;//递归边界,将叶子节点添加了两个nullptr节点,同时可以处理只有一个节点的树的情况
if (pRoot1 == nullptr || pRoot2 == nullptr)
return false;//对应位置,一个节点存在,一个节点不存在,该二叉树肯定就不镜像相等
if (pRoot1->m_dbValue != pRoot2->m_dbValue)
return false;
return isSymmetrical(pRoot1->m_pLeft, pRoot2->m_pRight) && isSymmetrical(pRoot1->m_pRight, pRoot2->m_pLeft);
}
复习:
很棒的递归思路,特别是最后的return的返回值,代码非常简洁。
二刷代码:
struct BinaryTreeNode
{
int m_Value;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
bool isSymmetrical(BinaryTreeNode* pRoot)
{
return isSymmetrical(pRoot, pRoot);
}
bool isSymmetrical(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
if (pRoot1 == nullptr&&pRoot2 == nullptr)
return true;
if (pRoot1 == nullptr || pRoot2 == nullptr)
return false;
if (pRoot1->m_Value != pRoot2->m_Value)
return false;
return isSymmetrical(pRoot1->m_pLeft, pRoot2->m_pRight) &&
isSymmetrical(pRoot1->m_pRight, pRoot2->m_pLeft);
}