Invert a binary tree.
4
/ \
2 7
/ \ / \
1 3 6 9
to
4
/ \
7 2
/ \ / \
9 6 3 1
Trivia:
This problem was inspired by this original tweet by Max Howell:
Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so fuck off.
s思路:
1. 树的操作,遍历!
2. 先来recursive,就是交换root下面的两个指针的位置即可!这个是post-order遍历
3. 再看iterative.in-order和pre-order都写过,还没做过post-order的iterative遍历,试一下。在脑海里过了一遍,发现做法和pre-order竟然很一样,都需要stack+pre+pnow来做
4. 再次体会recursive和iterative的不同之处:recursive是top-down的方法,从根开始,一层一层的剥开问题进入更深的层次,当然这个不是无底洞,最深的层次就是问题的边界了,当然离不开我最喜欢谈论的边界,这个边界也是元问题,最基本的问题,最简单的问题,最显而易见的问题,一切复杂的变化由此出。在底层的问题答案显而易见,回答了底层问题,然后就逐渐又一层一层的回到上层,边回来边解决问题,也就是说,recursive是从顶到底,然后先解决底层问题在从底到顶一路解决问题。
5. iterative本质也是这样,但需要自己来搭框架,不像recursive利用回溯和计算机结构自然完成这个过程。iterative也需要从顶到底,用stack存数据,是为了到底解决了底层问题还能依靠stack里存的指针回到上层,继续解决上层的问题。也就是说stack是时空穿梭机,能在层级结构中自由穿梭不同的层级!
//方法1:recursive
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
//
if(!root) return NULL;
TreeNode* tmp=root->left;
root->left=invertTree(root->right);//先左
root->right=invertTree(tmp);//再右
return root;//后根
}
};
//方法2:iterative. stack+pre指针+pnow指针.post-order和pre-order套路一样!
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
//
if(!root) return NULL;
stack<TreeNode*> ss;
TreeNode* pnow=root,*pre=NULL,*tmp=NULL;
while(pnow||!ss.empty()){
while(pnow){
ss.push(pnow);
pnow=pnow->left;
}
pnow=ss.top();
if(pnow->right&&pnow->right!=pre){
pnow=pnow->right;
}else{
tmp=pnow->left;
pre=pnow;//bug:需要把pnow给pre,让pre来表明刚做了一件什么事情!
pnow->left=pnow->right;
pnow->right=tmp;
ss.pop();
pnow=NULL;//bug:pnow复位,因为新的pnow需要从stack里面取出
}
}
return root;
}
};