请完成一个函数,输入一个二叉树,该函数输出它的镜像。
例如输入:
示例 1:
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]
解:
这个同样利用递归是最容易理解的办法:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
//结束条件
if(root==NULL) return root;
//等价关系函数
//先要将左右子树交换
swap(root->left, root->right);
//TreeNode* temp = root->right;
//root->right = root->left;
//root->left = temp;
//然后将两个子树利用递归实现镜像
mirrorTree( root->right);
mirrorTree( root->left);
return root;
}
};
第二种方法:
就是利用栈顶弹出,交换栈顶节点的左右子树,对于这道题来说比较繁琐,了解即可。
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
//建立一个保存节点的栈空间
stack<TreeNode*> s;
//先把根节点插进去
s.push(root);
//节点不为空的时候就不断循环
while (!s.empty()) {
//把栈顶的根节点拿出来
TreeNode* node = s.top();
s.pop();
//要是拿出来的节点是空的就迅速重新开始判断
//这个判断不是为了防止只有一个子树
//就是当最后一个节点从栈中出去的时候,直接不用往下进行交换左右子树了
if (node == NULL) {
continue;
}
//拿出节点之后,交换该节点左右子节点
swap(node->left, node->right);
//然后再把左右子节点插到栈中重新开始
s.push(node->left);
s.push(node->right);
}
return root;
}
};
这个栈容器的作用是为了将一个个节点放进去,再从栈顶一个个弹出来,进行操作。这种方法和上一种递归方法相比的不同在于,上一种交换完左右节点之后,接下来就利用递归实现剩下的树的镜像。而这一种方法是一个个节点进行镜像。
问题:将一个个节点放进去再弹出来,这样反过来的顺序有什么意义?可不可以放到普通的容器里面再取出来?
我:感觉这个顺序其实没什么用,为什么,因为你看下面这种方法就是换成了队列插入:
和上一个没什么区别,就是把上一个栈顶弹出换成了队列头弹出,然后就没什么了。这个相比上一个还是先进先出的,所以说和顺序没什么区别,主要是需要一个容器来把一个个节点用一下再弃掉!
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode* node = q.front();
q.pop();
if (node == NULL) {
continue;
}
swap(node->left, node->right);
q.push(node->left);
q.push(node->right);
}
return root;
}
};
还有一种方法,这种方法是我做下一道判断二叉树是否是对称二叉树时看到的,这个方法和上面的区别在于,用这个方法,最后得出来的二叉树你可以去其他函数中调用,而上面的三种方法都不可以调用,为什么这么说呢,我将上面三种方法用在下一道题中,全部输入错误。
所以,下面这种方法的适用性更强更好!
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
if(root==NULL) return NULL;
//最核心的就是这一步了
TreeNode* res = new TreeNode(root->val);
// res=root;
//swap(res->right,res->left);
//下面注意两边左右不同
res->left=mirrorTree(root->right);
res->right=mirrorTree(root->left);
return res;
}
};
上面为什么一定要new出新的空间呢?
new的作用就是手动开辟一个空间,释放的时候必须手动释放,不能自动释放!
是不是为了防止释放掉?不太清清楚!