Flatten Binary Tree to Linked list

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
思路:三种写法 1) 维持一个全局变量作为Prev来进行threading,因为有了前后的节点,那么无论是单项还是双向的threading都可以做了 递归的写法
2) 使用stack模拟的非递归的写法,但是O(m)的空间复杂度,m是最长的left-left path的深度
3) 采用inorder threading的思想 Morris的写法,O(1)的空间复杂度
分别给出1) 和 3) 的写法
code :
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void tolist(TreeNode * root, TreeNode *& pre)
    {
        if (!root){
            return;
        }
        TreeNode * left_temp = root->left;
        TreeNode * right_temp = root->right;
        if (!pre){
            pre = root;
        }else{
            pre->right = root;  //因为这里root要跑去当pre的 right child,所以之前的tree结构要被破坏,所以要先保存
            pre->left = NULL;
            pre = root;
        }
        tolist(left_temp,pre);
        tolist(right_temp,pre);
    }
    void flatten(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        TreeNode * pre = NULL;
        tolist(root,pre);
    }
};

 这个code没办法AC,是因为构建list的时候,破坏了原来tree的结构,没法继续遍历下去,除非复制一棵tree或者先output到一个vector,然后再构造出一个list,可是那么traversal的时候O(1)的复杂度又有什么意义呢?

 NO AC!!!!

class Solution {
public:
    void flatten(TreeNode *root){
        if (!root){
            return;
        }
        TreeNode * prev = NULL;
        TreeNode * current = root;
        TreeNode * temp = NULL;
        while(current){
            if (!current->left){ //叶节点都得用这种方式访问
                //无论是InOrder还是PreOrder,这个节点都需要访问了 要么是叶节点 要么是没有左子树
                //ans.push_back(current->val);
                
                //先保存一下current right节点
                temp = current->right;
                if (prev) {
                    prev->right = current;
                    prev->left = NULL;
                    prev = current;
                }else{
                    prev = current;
                }
                
                //current = current->right; //因为这个指针已经threading,所以将来不怕right为空的情况
                current = temp;
            }else{
                TreeNode *  p = current->left;
                while(p->right && p->right != current){
                    p = p->right;
                }
                if (!p->right){ //threading first time
                    p->right = current;
                    //如果是preOder的话,第一遍下来的时候就需要访问
                    //第二遍unthreading的时候,就不需要访问了
                    //ans.push_back(current->val); 
                    
                    temp = current->right;
                    if (prev) {
                        prev->right = current;
                        prev->left = NULL;
                        prev = current;
                    }else{
                        prev = current;
                    }
                    
                    //current = current->left;
                    current = temp;
                }else{  //unthreading second time  access it
                        //这种情况只是不想破坏原来二叉树的结构,要不然可以直接访问current节点,而不用再过一遍
                    //ans.push_back(current->val); //PreOrder的话,那么要转到右边去,就不需要访问了
                    p->right = NULL;
                    current = current->right;
                }
            }
        }
    }
};

 

posted @ 2013-02-13 14:28  一只会思考的猪  阅读(174)  评论(0编辑  收藏  举报