一、题目描述
个人的ac代码:(层序遍历,对称的去看):
注:如何删除vector的第一个值
auto iter=que.begin(); iter=que.erase(iter);
class Solution
{
public:
bool isSymmetric(TreeNode* root)
{
TreeNode* p;bool flag=true;
if(root==nullptr)return true;
vector<TreeNode*>que;
que.push_back(root);
while(!que.empty()&&flag)
{
int cnt=que.size();
int i=0,j=cnt-1;
while(i<=j)
{
if(que[i]->left)//如果i指针有左孩子,那么j有同等的右孩子
if(que[j]->right==nullptr||que[i]->left->val!=que[j]->right->val)
{flag=false;break;}
if(que[i]->right)//如果i指针有右孩子,那么j有同等的左孩子
if(que[j]->left==nullptr||que[i]->right->val!=que[j]->left->val)
{flag=false;break;}
if(que[j]->left)//j指针有左孩子,i同等的右孩子(反向判断一下,否则部分样例进不来)
if(que[i]->right==nullptr||que[j]->left->val!=que[i]->right->val)
{flag=false;break;}
if(que[j]->right)//j指针有右孩子,那么i有同等的左孩子
if(que[i]->left==nullptr||que[j]->right->val!=que[i]->left->val)
{flag=false;break;}
i++;j--;
}
for(int i=0;i<cnt;i++)
{
auto iter=que.begin();
p=que[0];iter=que.erase(iter);
if(p->left) que.push_back(p->left);
if(p->right) que.push_back(p->right);
}//完成本层的结点的读取
}
return flag;
}
};
二、参考思路与代码:
感悟:二叉树类的题目一定要优先确定好利用什么样的遍历顺序
1.递归法:![101. 对称二叉树1](https://i-blog.csdnimg.cn/blog_migrate/1e58e5ee8af1aa1e0f5d26958056ad56.png)
本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。
正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。
但都可以理解算是后序遍历,尽管已经不是严格上在一个树上进行遍历的后序遍历了。
其实后序也可以理解为是一种回溯,当然这是题外话,讲回溯的时候会重点讲的。
递归三部曲:
C++完整代码:
class Solution { public: bool compare(TreeNode* left, TreeNode* right) { // 首先排除空节点的情况 if (left == NULL && right != NULL) return false; else if (left != NULL && right == NULL) return false; else if (left == NULL && right == NULL) return true; // 排除了空节点,再排除数值不相同的情况 else if (left->val != right->val) return false; // 此时就是:左右节点都不为空,且数值相同的情况 // 此时才做递归,做下一层的判断 bool outside = compare(left->left, right->right); // 左子树:左、 右子树:右 bool inside = compare(left->right, right->left); // 左子树:右、 右子树:左 bool isSame = outside && inside; // 左子树:中、 右子树:中 (逻辑处理) return isSame; } bool isSymmetric(TreeNode* root) { if (root == NULL) return true; return compare(root->left, root->right); } };
2.迭代法
要注意,这里的迭代法可不是前中后序的迭代写法,因为本题的本质是判断两个树是否是相互翻转的,其实已经不是所谓二叉树遍历的前中后序的关系了。可以使用队列来比较两个树(根节点的左右子树)是否相互翻转,(注意这不是层序遍历)
①队列(成对的比较)
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (root == NULL) return true;
queue<TreeNode*> que;
que.push(root->left); // 将左子树头结点加入队列
que.push(root->right); // 将右子树头结点加入队列
while (!que.empty()) { // 接下来就要判断这两个树是否相互翻转
TreeNode* leftNode = que.front(); que.pop();
TreeNode* rightNode = que.front(); que.pop();
if (!leftNode && !rightNode) { // 左节点为空、右节点为空,此时说明是对称的
continue;
}
// 左右一个节点不为空,或者都不为空但数值不相同,返回false
if ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) {
return false;
}
que.push(leftNode->left); // 加入左节点左孩子
que.push(rightNode->right); // 加入右节点右孩子
que.push(leftNode->right); // 加入左节点右孩子
que.push(rightNode->left); // 加入右节点左孩子
}
return true;
}
};
②栈
这个迭代法,其实是把左右两个子树要比较的元素顺序放进一个容器,然后成对成对的取出来进行比较,那么其实使用栈也是可以的。
只要把队列原封不动的改成栈就可以了,我下面也给出了代码。
class Solution { public: bool isSymmetric(TreeNode* root) { if (root == NULL) return true; stack<TreeNode*> st; // 这里改成了栈 st.push(root->left); st.push(root->right); while (!st.empty()) { TreeNode* leftNode = st.top(); st.pop(); TreeNode* rightNode = st.top(); st.pop(); if (!leftNode && !rightNode) { continue; } if ((!leftNode || !rightNode || (leftNode->val != rightNode->val))) { return false; } st.push(leftNode->left); st.push(rightNode->right); st.push(leftNode->right); st.push(rightNode->left); } return true; } };
三、相关题目推荐:
这两道题目基本和本题是一样的,只要稍加修改就可以AC。
- 100.相同的树
- 572.另一个树的子树