一、翻转二叉树
1.题目
2.思路
这道题最重要的函数是swap,然后采用层序遍历或者深度优先遍历
2.1 层序遍历
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
queue<TreeNode*> que;
if(root != NULL) que.push(root);//不能操作空结点
while(!que.empty()){
//遍历每一层
int size = que.size();
for(int i = 0;i < size;i++){
//取队列顶层数据
TreeNode* node = que.front();
//把数据删除
que.pop();
swap(node->left, node->right); // 节点处理
//结束条件+把结点左右结点加进去
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
}
return root;
}
};
2.2 递归法
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root == NULL) return root;
swap(root->left,root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
二、对称二叉树
1.题目
2.思路
对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,我们要比较的是两个树(这两个树是根节点的左右子树),所以在递归遍历的过程中,也是要同时遍历两棵树。
怎么比较?
比较的是两个子树的里侧和外侧的元素是否相等。
2.1 递归法
本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。
迭代法
1.确定递归函数的参数和返回值
因为我们要比较的是根节点的两个子树是否是相互翻转的,进而判断这个树是不是对称树,所以要比较的是两个树,参数自然也是左子树节点和右子树节点。返回值自然是bool类型。
2.确定终止条件
要比较两个节点数值相不相同,首先要判断两个节点是否为空,避免操作空指针。
节点为空的情况有:(注意我们比较的其实不是左孩子和右孩子,所以如下称之为左节点右节点)
- 左节点为空,右节点不为空,不对称,return false
- 左不为空,右为空,不对称 return false
- 左右都为空,对称,返回true
此时已经排除掉了节点为空的情况,那么剩下的就是左右节点不为空:
- 左右都不为空,比较节点数值,不相同就return false
此时左右节点不为空,且数值也不相同的情况我们也处理了。
把以上情况都排除之后,剩下的就是 左右节点都不为空,且数值相同的情况。
3.确定单层递归的逻辑
此时才进入单层递归的逻辑,单层递归的逻辑就是处理 左右节点都不为空,且数值相同的情况。
- 比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
- 比较内侧是否对称,传入左节点的右孩子,右节点的左孩子。
- 如果左右都对称就返回true ,有一侧不对称就返回false 。
整体代码:
class Solution {
public:
bool compare(TreeNode*left,TreeNode*right){
//排除空节点情况
if(left == NULL && right != NULL) return false;
else if(right == NULL && left != 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.2迭代法
class Solution {
public:
bool isSymmetric(TreeNode* root) {
queue<TreeNode*> que;
if(root == NULL) return true;
if(root) que.push(root->left);
if(root) 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 isSameTree(TreeNode* p, TreeNode* q) {
if(p == NULL && q == NULL) return true;
else if(p == NULL && q != NULL) return false;
else if(p != NULL && q == NULL) return false;
else if(p->val != q->val) return false;
bool outside = isSameTree(p->left,q->left);
bool inside = isSameTree(p->right,q->right);
return outside && inside;
}
};