226. 反转二叉树
题目描述:给你一棵二叉树的根节点 root
,翻转这棵二叉树,并返回其根节点。
解答:
想要翻转二叉树,其实就把每一个节点的左右孩子交换一下就可以了。关键在于遍历顺序,前中后序、层序应该选哪一种遍历顺序?遍历的过程中去翻转每一个节点的左右孩子就可以达到整体翻转的效果。
前序、后序、层序都比较易于实现,但是只有中序有点麻烦。
法一:采用递归法
之前有写过递归法实现前中后序遍历:二叉树的递归遍历_清榎的博客-CSDN博客
此处采用前序遍历的递归解法。
按照递归三要素进行思考:
参数和返回值:将根节点传参,直接修改即可,无需返回值。
终止条件:遇到为空的节点进行返回。
处理逻辑:前序遍历中左右,每次处理中间节点时进行翻转即可,左右进行递归处理。
动画如下:
代码实现:
class Solution {
public:
void reverseTree(TreeNode* cur){
if (cur == NULL)
return;
swap(cur->left, cur->right);
reverseTree(cur->left);
reverseTree(cur->right);
}
TreeNode* invertTree(TreeNode* root) {
reverseTree(root);
return root;
}
前面提到中序遍历较为麻烦,但是还是可以实现,此处用递归法实现一个:
class Solution {
public:
void reverseTree(TreeNode* cur){
if (cur == NULL)
return;
reverseTree(cur->left);
swap(cur->left, cur->right);
reverseTree(cur->left);//因为左右节点已经交换,此时的左节点才是前面的右节点
}
TreeNode* invertTree(TreeNode* root) {
reverseTree(root);
return root;
}
};
法二:采用迭代法(以前序遍历为例)
迭代法实现前序遍历前文已经提到:二叉树的迭代法遍历、统一迭代法遍历_清榎的博客-CSDN博客
此处主要修改一下访问中间节点的操作即可,将放入结果集中改为交换左右节点。
代码实现:
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (root == NULL) return root;
stack<TreeNode*> st;
st.push(root);
while(!st.empty()) {
TreeNode* node = st.top(); // 中
st.pop();
swap(node->left, node->right);
if(node->right) st.push(node->right); // 右
if(node->left) st.push(node->left); // 左
}
return root;
}
};
法三:采用层序遍历(广度优先遍历)。
按照层序遍历的方式进行,每次遍历到一个节点时交换节点的左右孩子,然后再将其子节点入队即可。
代码实现:
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
queue<TreeNode*>que;
if (root) 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;
}
};
总结:
针对二叉树的问题,解题之前一定要想清楚究竟是前中后序遍历,还是层序遍历。