Given a binary tree, flatten it to a linked list in-place.
For example,
Given
1
/ \
2 5
/ \ \
3 4 6
The flattened tree should look like:
1
\
2
\
3
\
4
\
5
\
6
之前的一个解法: 遍历返回首节点,所以,在左右孩子都有的情况下,要遍历左边来拿到尾的节点。 (这个是可以通过的)
public class Solution {
public void flatten(TreeNode root) {
if(root == null) return;
TreeNode node = tra(root);
}
static TreeNode tra(TreeNode root){
if(root.left == null && root.right == null) return root;
if(root.left == null) {
root.right = tra(root.right);
return root;
}
if(root.right == null){ //careful to deal with the left
root.right = tra(root.left);
root.left = null;
return root;
}
TreeNode left = tra(root.left);
TreeNode cur = left; while(cur.right != null) cur = cur.right;
cur.right = tra(root.right);
left.left = null; root.left = null; root.right = left;
return root;
}
}
自创新的解法,是返回最后的节点,但是要输入 pre 节点。 这个感觉更有效一些,但是 大数据没通过。
public void flatten(TreeNode root) {
if(root == null) return;
TreeNode pre = new TreeNode(-1);
TreeNode last = tra(root,pre);
pre.right = null;
}
private TreeNode tra(TreeNode root, TreeNode pre){
// return last node
if(root == null) return null;
else{
pre.right = root;
pre.left = null;
}
if(root.left == null && root.right == null)
return root;
else if(root.right == null)
return tra(root.left,root);
else if(root.left == null)
return tra(root.right,root);
else {
TreeNode r = root.right;
TreeNode left = tra(root.left,root);
return tra(r,left);
}
}
1. 给left 赋值 null 的动作都是当前位置对 pre做的;
2. 由于1.的原因,当前会对pre 的left right做修改,所以对最后一种 left right 都不为null 的情况,要先存一下后面再遍历的 right 节点,免得对left 的遍历修改root后找不到right了。
跑出来比一般的是要少几十秒哈 :)
下午跑几个test case 看看。
其他的,发现一个 比较简洁的用 C++ 的,再研究下:
class Solution {
public:
void build(TreeNode *root, TreeNode *&tmp)
{
if(root)
{
build(root->right, tmp);
build(root->left, tmp);
root->right=tmp;
tmp=root;
root->left=NULL;
}
}
void flatten(TreeNode *root) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
TreeNode *tmp=NULL;
build(root, tmp);
}
};