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; } } } } };