Flatten Binary Tree to Linked List
Flatten a binary tree to a fake "linked list" in pre-order traversal.
Here we use the right pointer in TreeNode as the next pointer in ListNode.
http://www.lintcode.com/en/problem/flatten-binary-tree-to-linked-list/
Solution 1
假设某节点的左右子树T(root->left)和T(root->right)已经flatten成linked list了:
1
/ \
2 5
\ \
3 6 <- rightTail
\
4 <- leftTail
如何将root、T(root->left)、T(root->right) flatten成一整个linked list?显而易见:
- temp = root->right
- root->right = root->left
- root->left = NULL
- leftTail->right = temp
这里需要用到已经flatten的linked list的尾部元素leftTail, rightTail。所以递归返回值应该是生成的整个linked list的尾部。
//O(n) rum time
//O(h) stack space
class Solution {
public:
/**
* @param root: a TreeNode, the root of the binary tree
* @return: nothing
*/
void flatten(TreeNode *root) {
// write your code here
TreeNode *list_tail = NULL;
list_tail = flattenHelper(root);
}
TreeNode *flattenHelper(TreeNode *root) {
if(root == NULL) return NULL;
TreeNode * leftTail = flattenHelper(root->left);
TreeNode *rightTail = flattenHelper(root->right);
if(root->left) {
TreeNode *tmp = root->right;
root->right = root->left;
root->left = NULL;
leftTail->right = tmp;
}
if(rightTail != NULL) return rightTail;
if(leftTail != NULL ) return leftTail;
return root;
}
};
Solution 2
一个简单的解法,先preorder存下所有node,再构建list,但是这样需要O(n) space + O(logn) sapce for stack.
class Solution {
public:
/**
* @param root: a TreeNode, the root of the binary tree
* @return: nothing
*/
void flatten(TreeNode *root) {
// write your code here
if(root == nullptr) return;
vector<TreeNode*> nodelist;
preorder(root, nodelist);
int n = nodelist.size();
for(int i=0; i<n-1; i++) {
nodelist[i]->right = nodelist[i+1];
nodelist[i]->left = nullptr;
}
nodelist[n-1]->right = nullptr;
nodelist[n-1]->left = nullptr;
}
void preorder(TreeNode *root, vector<TreeNode*> &nodelist) {
if(root == NULL) return;
nodelist.push_back(root);
preorder(root->left, nodelist);
preorder(root->right, nodelist);
}
};
Solution 3
一个牛逼的写法,修改morris traversal,O(1) space。
void flatten(TreeNode *root) {
// write your code here
if(root == nullptr) return;
TreeNode *cur = root;
TreeNode *prev = root;//中序遍历中cur的前置节点
while (cur) {
if(cur->left == NULL) {
//output cur
//for pre-order travesal
cur = cur->right;
} else {
//左孩子不为空,找到它中序遍历的前置节点prev
prev = cur->left;
while (prev->right != NULL && prev->right != cur){
prev = prev->right;
}
if(prev->right == NULL) {
//output cur
//for pre-order travesal
prev->right = cur;
cur = cur->left;
} else { //prev->right == cur, second time access this prev
TreeNode *tmp = cur->right;//这里是关键,其实solution 1
cur->right = cur->left;//里面的LeftTail就是这里的prev
cur->left = NULL;//所以这里还是那样的四步
prev->right = tmp;
cur = tmp;//move to right
}
}
}
}