114. Flatten Binary Tree to Linked List
题目中要求我们把一个二叉树按先序遍历“拍扁”,看到这题的第一反应肯定是先序遍历同时建个链表返回表头就好了?
有意思的是题目要求的结果是一个不含左孩子的树形结构,返回类型也是void,即提醒你要在原结构里修改,所以凡是含有new TreeNode的解决方案肯定是不合适的,在实际的场景中,去拷贝一个非常大的树的内存消耗也是很大的
Solution:
先来看解法,如果让你而不是计算机来完成这个操作,你会怎么做?
1
/ \
2 5
/ \ \
3 4 6
对于上面这个结构,我是这样操作的:
首先不管5,6(揣兜里),把1画在纸上,再不管4(也揣兜里),把2连在1右侧画在纸上,然后把3连在2右侧画在纸上:
纸上:
1
\
2
\
3
兜里:
4
5
\
6
左边到头了,这时再把兜里的4掏出来接到3后面画纸上;又到头了,只能从兜里掏出5和6;5画在4后面,6揣到兜里;又到头了,再从兜里掏出6…
想必到了这里规律已经能看出来了,左边的画到上一个节点后面,右边的揣兜里,到头了就从兜里掏,掏出来的子树重复以上过程…值得一提的是,我们用的这个兜显然是个后入先出的结构
就这样,用一个内容是<TreeNode*>的栈结构去当兜存右子树,再把左孩子移到右侧的算法设计完成
Talk is cheap:
/**
* 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:
void flatten(TreeNode* root) {
if (!root) return;
stack<TreeNode*> waitstack;
TreeNode* cur = root;
while(cur->right || cur->left || !waitstack.empty()) {
// cout <<"cur->val"<<cur->val
// <<"cur->left"<<cur->left
// <<"cur->right"<<cur->right
// <<"stack.size()"<<waitstack.size()
// <<endl;
while(cur->right && !cur->left) {
cur = cur->right;
}
if(cur->right) {
waitstack.push(cur->right);
cur->right = nullptr;
}
if(cur->left) {
cur->right = cur->left;
cur->left = nullptr;
cur = cur->right;
}else if(!waitstack.empty()) {
cur->right = waitstack.top();
waitstack.pop();
cur = cur->right;
}
}
}
};