题目描述
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
思路1:利用剑指offer第27题二叉树的镜像。先得到二叉树的镜像,再判断是否相同
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
if (pRoot == nullptr)
return true;
TreeNode* cloneRoot = clone(pRoot);
Mirror(cloneRoot);
return isSameTree(pRoot,cloneRoot);
}
TreeNode* clone(TreeNode* pRoot) { //深拷贝该二叉树
if (pRoot == nullptr)
return nullptr;
TreeNode* cloneRoot = new TreeNode(pRoot->val);
cloneRoot->left = clone(pRoot->left);
cloneRoot->right = clone(pRoot->right);
return cloneRoot;
}
void Mirror(TreeNode* cloneNode) { //二叉树的镜像
if (cloneNode == nullptr)
return;
swap(cloneNode->left, cloneNode->right);
Mirror(cloneNode->left);
Mirror(cloneNode->right);
}
bool isSameTree(TreeNode* t1,TreeNode* t2){ //判断两棵树是否相同
if(t1==nullptr && t2==nullptr)
return true;
if(t1!=nullptr && t2!=nullptr && t1->val==t2->val) {
bool left = isSameTree(t1->left, t2->left);
bool right = isSameTree(t1->right, t2->right);
return left && right;
}
return false;
}
};
思路2:从根节点的左右子树开始判断,若左子树的左子树与右子树的右子树相等,且左子树的右子树与右子树的左子树相等,就递归向下判断各子树
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
if (pRoot == nullptr)
return true;
return comroot(pRoot->left, pRoot->right);
}
bool comroot(TreeNode* left, TreeNode* right) {
if (left == nullptr) return right == nullptr; //若左子树为空,就判断右子树是否为空,不为空返回true,为空就返回false
if (right == nullptr) return false; //注意:能执行到这步,说明左子树不为空;若右子树为空,就返回false
if (left->val != right->val)
return false;
return comroot(left->left, right->right) && comroot(left->right, right->left);
}
};
思路3:BFS 使用一个指针队列来保存成对的节点,先进先出
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
queue<TreeNode*> s;
s.push(pRoot->left);
s.push(pRoot->right);
while (!s.empty())
{
TreeNode* left1 = s.front(); //成对的出队
s.pop();
TreeNode* right1 = s.front();
s.pop();
if (left1 == nullptr && right1 == nullptr) continue; //若都为空,继续
if (left1 == nullptr || right1 == nullptr) return false; //若一个为空,返回false
if (left1->val != right1->val) return false; //若都不为空,比较当前值,值不等,返回false
//确定入队顺序,每次入队都是成对成对的,如left->left, right->right ;left->rigth,right->left
s.push(left1->left);
s.push(right1->right);
s.push(left1->right);
s.push(right1->left);
}
return true;
}
};
思路4:同思路3,使用栈来保存成对的节点,先进后出
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
if (pRoot == nullptr)
return true;
stack<TreeNode*> s;
s.push(pRoot->left);
s.push(pRoot->right);
while (!s.empty())
{
TreeNode* right1 = s.top();
s.pop();
TreeNode* left1 = s.top();
s.pop();
if (left1 == nullptr && right1 == nullptr) continue;
if (left1 == nullptr || right1 == nullptr) return false;
if (left1->val != right1->val) return false;
s.push(left1->left);
s.push(right1->right);
s.push(left1->right);
s.push(right1->left);
}
return true;
}
};
【注!】本题给出一种 错误 思路,用例通过率只能90%
错误解法:判断前序遍历和后序遍历是否互为逆。-》因为vector无法确定一棵树的结构,例如,子节点不清楚具体在哪父节点上,比如:{5,5,5,5,#,#,5,5,#,5}不是对称二叉树,但会被误判为true!要注意。若要用这种方法,应该把nullptr也放入数组!
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
if (pRoot == nullptr)
return true;
vector<int> prearr;
vector<int> lastarr;
prearr = preOrder(pRoot, prearr);
lastarr = lastOrder(pRoot, lastarr);
reverse(lastarr.begin(),lastarr.end()); //(lastarr.rbegin(), lastarr.rend());
if (prearr == lastarr)
return true;
return false;
}
vector<int> preOrder(TreeNode* pRoot,vector<int>& prearr) {
if (pRoot == nullptr)
return prearr;
prearr.push_back(pRoot->val);
preOrder(pRoot->left, prearr);
preOrder(pRoot->right, prearr);
return prearr;
}
vector<int> lastOrder(TreeNode* pRoot, vector<int>& lastarr) {
if (pRoot == nullptr)
return lastarr;
lastOrder(pRoot->left, lastarr);
lastOrder(pRoot->right, lastarr);
lastarr.push_back(pRoot->val);
return lastarr;
}
};