题意:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
分析:通常我们有3种不同的二叉树遍历算法,即前序遍历,中序遍历和后序遍历,在这3种遍历算法中,都是先遍历左子节点再遍历右子节点,针对这道题,我们是否可以定义这样一种遍历算法,先遍历右子节点再遍历左子节点?即先遍历父节点,再遍历它的右子节点,最后遍历它的左子节点。这样如果我们得到的两个序列是完全相同的,那么我们就可以说二叉树是对称的。
特殊的,如果这棵二叉树的所有节点的值都是一样的,那么我们将无法依靠前序遍历和前序遍历的对称遍历序列区分这棵二叉树,此时,其实我们只需要在遍历二叉树的时候把遇到的nullptr指针也考虑进来就行了,我们可以把空指针设置成一个INF值标记起来。
//其中一种想法,定义一种新型的遍历方式,首先遍历右子树,接着是根,最后是左子树
//这样得到的序列和前序遍历得到的序列进行比较,如果相等那么这棵树是对称的
//特别注意一种情况,就是整棵树的val值都是同一个值,这时得到的序列都是同一个值,但是这棵树可能结构并不是对称的
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
const int INF = 0x3f3f3f3f;
class Solution {
private:
vector<int>vec1;
vector<int>vec2;
public:
Solution()
{
vec1.clear();
vec2.clear();
}
~Solution()
{
}
void dfsPreOrder(TreeNode* pRoot)
{
if(pRoot==nullptr) {
vec1.push_back(INF);
return;
}
vec1.push_back(pRoot->val);
dfsPreOrder(pRoot->left);
dfsPreOrder(pRoot->right);
}
void dfsMyOrder(TreeNode* pRoot)
{
if(pRoot==nullptr) {
vec2.push_back(INF);
return;
}
vec2.push_back(pRoot->val);
dfsMyOrder(pRoot->right);
dfsMyOrder(pRoot->left);
}
bool isSymmetrical(TreeNode* pRoot)
{
if(pRoot==nullptr) return true;
//得到前序序列 注意特殊情况,我们要把nullptr值也记录下来
dfsPreOrder(pRoot);
//根据自己定义的遍历方式进行遍历
dfsMyOrder(pRoot);
for(int i=0;i<vec1.size();i++)
if(vec1[i]!=vec2[i]) return false;
return true;
}
};