第一次自己做,思路出现了问题:对称二叉树不是一棵树的左右子节点相等,而是反转二叉树之后和原二叉树一样!
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
if(!pRoot) return false;
bool flag = true;
postorder(pRoot, flag);
return flag;
}
void postorder(TreeNode* pRoot, bool& flag) {
if(!pRoot) return;
//if( (pRoot->left || pRoot->right) && (pRoot->left && pRoot->left) ) //逻辑异或,C++中没有对应的运算符
if( (pRoot->left == nullptr)^(pRoot->right == nullptr) ||
(pRoot->left && pRoot->right && pRoot->left->val!=pRoot->right->val) )
{
flag = false;
return;
}
if(flag && pRoot->left) postorder(pRoot->left, flag);
if(flag && pRoot->right) postorder(pRoot->right, flag);
}
};
在看了书上的解题思路,扫了一眼代码之后,自己实现的程序,出现的问题:
1、递归时,只加 flag 会造成程序错误:这是显然的,没有判断pRoot1,pRoot2 就对它们取子节点,如果pRoot1/2为空则会出现错误。报错比较奇怪,是栈溢出,递归调用不会无穷递归下去的,肯定会到叶子节点出现上述的“取空节点的子节点”的错误。
2、if 条件中加入类似 pRoot->left 条件也不对,如果一个节点只有左子树,无右子树,比如[866577],会因为不进行递归,提前返回导致错误的返回true。因为先序遍历递归写法的惯性会让人习惯的写上 pRoot1->left 形式的判断。
3、正确的做法是,if 条件中加入 flag一旦出现 false 就返回,加入pRoot1,pRoot2判断不为空再进行递归。
4、一个小点:空树返回true
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
if(!pRoot) return true;
bool flag = true;
biTraversal(pRoot, pRoot, flag);
return flag;
}
//对一棵树同时进行先序遍历和对称后的先序遍历
void biTraversal(TreeNode* pRoot1, TreeNode* pRoot2, bool& flag) {
if((!pRoot1 && !pRoot2) || (pRoot1 && pRoot2 && pRoot1->val==pRoot2->val)) {
flag = true;
}
else {
flag = false;
}
//if(flag && pRoot1->left && pRoot2->right) biTraversal(pRoot1->left, pRoot2->right, flag);
//if(flag && pRoot1->right && pRoot2->left) biTraversal(pRoot1->right, pRoot2->left, flag);
if(flag && pRoot1 && pRoot2) biTraversal(pRoot1->left, pRoot2->right, flag);
if(flag && pRoot1 && pRoot2) biTraversal(pRoot1->right, pRoot2->left, flag);
}
};
书上的代码写法,比我自己写的要优雅很多:
之前被迫引入flag变量,就是因为不知道怎么合理的设置return:在这里不需要加上“ == ”时return true,实际上加上就是错的,只有遍历完整棵树没有出现过false才可以return true。书上的代码遇到了false也会不再继续递归而是开始向上返回。
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
return biTraversal(pRoot, pRoot);
}
//对一棵树同时进行先序遍历和对称后的先序遍历
bool biTraversal(TreeNode* pRoot1, TreeNode* pRoot2) {
if (pRoot1==nullptr && pRoot2==nullptr) return true; //两个都为nullptr
if (pRoot1==nullptr || pRoot2==nullptr) return false; //只有一个为nullptr
if (pRoot1->val != pRoot2->val) return false;
//之前被迫引入flag变量,就是因为不知道怎么合理的设置return:
//在这里不需要加上 == 时return true,实际上加上就是错的,只有遍历完整棵树才可以return true
return biTraversal(pRoot1->left, pRoot2->right) && biTraversal(pRoot1->right, pRoot2->left);
}
};