LeetCode 114. Flatten Binary Tree to Linked List
Recursive
一开始我想用preorder加上prev指针来做,但是很快就发现了问题。由于preorder,root先处理,而在本题中,即先将root加到之前的prev之后。假如树是 (1 (2) (3)),dfs到节点2时,prev->right=root 会使得1的右儿子变成2,这会使得节点1的右子树丢失,而且会造成死循环。
PreOrder
备份 root->right,而且 root->left 要在递归左子树之后再置为 null,或者可以left和right都copy一份。
Easy-Understand-Java-Recursive-solution-beat-100-with-Explanation
Java-pre-order-and-post-order-solution-same-idea-with-114.-Flatten-Binary-Tree-to-Linked-List
PostOrder
有一个巧妙避免上述问题的方法是,将preorder的顺序反过来,即 (right, left, root),从后往前构建linked list。这样根最后处理,无论我们怎么修改root的left和right都不会有任何问题,因为左子树和右子树都已经递归完毕了。
之前思路中prev是记录linked list最后一个元素。现在我们反过来之后,我们需要记录linked list第一个元素,记作first。
class Solution { public: TreeNode *first=NULL; void flatten(TreeNode* root) { if (root==NULL) return; flatten(root->right); flatten(root->left); root->right = first; root->left = NULL; first = root; } };
时间复杂度 O(n) 空间复杂度 O(h)
实际上,上述问题只有preorder会出现,inorder和postorder都是没有问题的。
inorder的例子可以见 LeetCode 426. Convert Binary Search Tree to Sorted Doubly Linked List
Iterative
PreOrder Iterative
preorder非递归第一种写法由于stack的存在,左右儿子放到了stack里,因此修改当前节点的左右节点没有影响。
preorder第二种写法就不行了,和递归中的出现的问题一样,利用copy节点的方法可能可以,但是太过繁琐。
class Solution { public: void flatten(TreeNode* root) { if (root==NULL) return; TreeNode *prev=NULL; stack<TreeNode *> s({root}); while (!s.empty()){ TreeNode *cur=s.top(); s.pop(); if (prev!=NULL){ prev->right = cur; prev->left = NULL; } prev = cur; if (cur->right) s.push(cur->right); if (cur->left) s.push(cur->left); } } };
Iterative without Stack
本题也可以直接非递归来做。每次把左子树移到右边,接上右子树。
http://www.cnblogs.com/grandyang/p/4293853.html 里有图,很形象。
class Solution { public: void flatten(TreeNode* root) { TreeNode *p=root; while (p){ if (p->left){ TreeNode *q=p->left; while (q->right) q=q->right; q->right = p->right; p->right = p->left; p->left = NULL; } p = p->right; } } };
Others
Recursive [Not optimal]
树里的 divide and conquer 感觉和 postorder traversal 就是一个东西,反正都是递归。
下面方法返回了 root ,也可以不返回,直接用 flatten 自己递归也行。
class Solution {
public:
void flatten(TreeNode* root) {
helper(root);
}
TreeNode *helper(TreeNode* root) {
if (root==NULL) return NULL;
TreeNode *left=helper(root->left);
TreeNode *right=helper(root->right);
root->left = NULL;
root->right = left;
TreeNode *cur=root;
while (cur->right!=NULL) cur=cur->right;
cur->right = right;
return root;
}
};
Reference