-
题目:
给定一个二叉树,返回它的镜像二叉树; -
思路:
将一颗二叉树镜像,相当于交换它的所有节点的左右孩子;
因此本题等价于在遍历二叉树时交换每个结点的左右孩子;
可选的遍历方式:前,中,后,层序均可,只要可以遍历二叉树即可,下面分别列出递归和迭代写法:
1.递归:O(n):遍历一次树的所有节点,O(n):递归n次所占的栈空间
注意点:
①其实代码中的return没什么用,作用只是返回当前节点,如果删掉这一句也能完成镜像操作,只是没法返回最终的头节点(其实就是本来的头节点);
②递归操作时,并不需要返回值做什么事,因此不用去接住下一层的返回值;
③注意遍历顺序:swap操作放在前面或后面均可,但放在中间会出错,因为中的操作本就是交换左右孩子,因此要么先交换再递归的处理左右孩子,要么先递归到最底层再交换左右孩子均可,但如果swap放在中间,会导致swap前后的两个递归操作所基于的“左右”发生了改变;
//写法1:先序遍历
class Solution {
public:
//交换树的每个节点的左右孩子
TreeNode* mirrorTree(TreeNode* root) {
swap(root->left, root->right);//中
mirrorTree(root->left);//
mirrorTree(root->right);
return root;//这里return的作用本就是返回当前节点
}
};
//写法2:中序遍历
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
if (!root) return nullptr;
mirrorTree(root->left);//递归操作root的左孩子
swap(root->left, root->right);//交换root的左右孩子
mirrorTree(root->left);//因为交换了root的左右孩子,所以现在的root->left就是原来的root->right
return root;
}
};
//写法3:后序遍历
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
if (!root) return nullptr;
mirrorTree(root->left);//左
mirrorTree(root->left);//右
swap(root->left, root->right);//中
return root;
}
};
2.迭代写法(借助栈或队列):O(n):遍历一遍树的所有节点,O(n):需要一个大小为n的额外空间
原理相同,只是借助的数据结构不用;
//写法1:栈(下面以前序遍历为例,中序和后序同理)
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
if (!root) return nullptr;
stack<TreeNode*> stk;
stk.push(root);//空结点不入栈
while (!stk.empty()) {
TreeNode* tmp = stk.top();
stk.pop();
swap(tmp->left, tmp->right);
if (tmp->left) stk.push(tmp->left);
if (tmp->right) stk.push(tmp->right);
}
return root;
}
};
//写法2:队列(层序遍历)
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
if (!root) return nullptr;
queue<TreeNode*> que;
que.push(root);//空结点不入队
while (!que.empty()) {
TreeNode* tmp = que.front();
que.pop();
swap(tmp->left, tmp->right);
if (tmp->left) que.push(tmp->left);
if (tmp->right) que.push(tmp->right);
}
return root;
}
};