好久没有刷力扣了,看看之前刷过的题目,再做一遍有新感觉
首先要搞清楚题目意思,不要一上来就下手做,发现规律,找准切入点,编码还是很快的。
对称二叉树是要求树成轴对称(并不是左右子树相同,因为刚做了相同二叉树的题目,先入为主,导致认为需要左右子树相同)
第一种解法-递归 DFS
一般树的问题可以考虑递归,以根节点为例,如果左右子树为空,则以本节点为根的树是对称二叉树,返回True;如果左右子树有一个节点为空,则返回False;如果左右子树都不为空且值相等,则继续迭代下一层,继续查看左子树的左子树与右子树的右子树 左子树的右子树与右子树的左子树;如果左右子树的值不等,直接返回False.代码如下:
bool isSymmetric(TreeNode* root) {
if(root == nullptr) return true;
return dfs(root->left, dfs->right);
}
bool dfs(TreeNode* left, TreeNode* right)
{
if(left == nullptr && right == nullptr) return true;
if(left == nullptr || right == nullptr) return false;
return (left->val == right->val) &&
dfs(left->left, right->right) &&
dfs(left->right, right->left);
}
第二种解法-层序遍历 BFS
层序是一种比较直观的做法,如果为对称二叉树,则每一层遍历出来的值是一个对称数组。每次都把应该对称的左右子节点先后放进queue中,判断的时候每次取出前两个(每次都取queue的front(),连续取两次),判断之后,再把left->left与right->right left->right与right->left放进去queue中。直到queue为空停止。代码如下:
bool isSymmetric(TreeNode* root) {
//首先对根节点有一个基本的判断
if(root->left == nullptr || root->right == nullptr)
return root->left == root->right;
if(root->left->val != root->right->val) return false;
queue<TreeNode*> q;
//把左右子树放进队列中
q.push(root->left);
q.push(root->right);
while(!q.empty())
{
//这地方完全没必要判断,每次放到队列中都是成对
//如果不是成对,已经在加入前返回了
//if(q.size() % 2) return false;
//每次取最前边queue.front(),pop()一次,再取,再pop()
TreeNode* left = q.front();
q.pop();
TreeNode* right = q.front();
q.pop();
//left->left 与 right->right的判断
if(left->left && right->right)
{
if(left->left->val != right->right->val) return false;
q.push(left->left);
q.push(right->right);
}
// 其中一个为空,另一个不为空,必false
else if((left->left == nullptr && right->right != nullptr)
|| (left->left != nullptr && right->right == nullptr))
return false;
//left->right 与 right->left 的判断
if(left->right && right->left)
{
if(left->right->val != right->left->val) return false;
q.push(left->right);
q.push(right->left);
}
// 其中一个为空,另一个不为空,必false
else if((left->right == nullptr && right->left != nullptr)
|| (left->right != nullptr && right->left == nullptr))
return false;
}
return true;
}
一年前的BFS解法
冗余内容较多,代码重构还是蛮有意思的事情
- 首先就是在每次遍历queue的地方,查看size()是否为2的倍数,这个地方比较多余
- 其次是对queue的内容是真正的按层是遍历判断的,其实没有必要,每次都是紧挨着自动塞进队列两个需要比对的节点,可以减少对queue.size()的判断。
bool isSymmetric(TreeNode* root) {
if(root == nullptr)
return true;
if(root->left == nullptr || root->right == nullptr)
return root->left == root->right;
if(root->left->val != root->right->val)
return false;
queue<TreeNode*> q;
q.push(root->left);
q.push(root->right);
while(!q.empty())
{
int size = q.size();
if(size % 2 != 0)
return false;
while(size > 0)
{
TreeNode* left = q.front();
q.pop();
TreeNode* right = q.front();
q.pop();
if(left->left != nullptr || right->right != nullptr)
{
if(left->left == nullptr || right->right == nullptr)
return false;
if(left->left->val != right->right->val)
return false;
}
if(left->left && right->right)
{
q.push(left->left);
q.push(right->right);
}
if(left->right != nullptr || right->left != nullptr)
{
if(left->right == nullptr || right->left == nullptr)
return false;
if(left->right->val != right->left->val)
return false;
}
if(left->right && right->left)
{
q.push(left->right);
q.push(right->left);
}
size -= 2;
}
}
return true;
}