您的位置:首页 > 编程语言 > Go语言

114. Flatten Binary Tree to Linked List

2016-02-19 09:51 357 查看

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


解析

很容易看到展开的tree是一个前序遍历的序列。基于这个想法我们可以

思路一:

前序遍历一次,并把结点保存起来;

针对保存的结点重新序列化;

这样时间复杂度为O(n),空间复杂度为O(n).

空间复杂度有点高,这时我发现如果能够使得叶子节点的right指向其后继的话,这样就很容易展成题目要求的形式了。

那么思路二:

使用前序遍历方法线索化二叉树,线索的对象为终端节点。

展开

思路二代码

void flatten(struct TreeNode* root) {
//前序叶子结点线索化
struct TreeNode throot;
struct TreeNode*pre=&throot;
struct TreeNode* p =root;
struct TreeNode*stack[50]={0};
int stacklen=0;
while(p||stacklen>0){
if(p){
if(pre->left==NULL&&pre->right == NULL){
pre->right = p;
}
pre = p;
stack[stacklen++]=p;
p=p->left;
}
else{
p=stack[--stacklen];
p=p->right;
}
}
//展开
p=root;
while(p){
if(p->left){
p->right=p->left;
p->left=NULL;
}
p=p->right;
}
}


代码分析

每个节点访问了两次,即2n,则时间复杂度为O(n).

空间复杂度依赖树的深度,树的深度为log2(n)~n。那么空间复杂度也是O(n).

对比思路一貌似一点优势也没有。哭了~~~~

高效方法

思路三:

1. 先让当前节点的右儿子指向左儿子,左儿子的“最右下”(即以左儿子为root前序遍历的最后一个结点)指向当前节点的原来的右儿子

2. 依次迭代即可。

思路三代码

void flatten(struct TreeNode* root) {
//链表的插入法
if(root==NULL) return;
struct TreeNode* p,*q,*s;
p=root;
q=NULL;
s=NULL;
while(p){
s=p->left;
if(s!=NULL){
q=p->right;
//寻找最右下结点
while(s->left||s->right){
if(s->right){
s= s->right;
}
else{
s=s->left;
}
}
s->right=q;
p->right=p->left;
p->left=NULL;
}
p=p->right;
}
}


思路4点击查看

代码

void flatten(struct TreeNode* root) {
//链表的插入法
if(root==NULL) return;
struct TreeNode* cur,*pre;
cur=root;
while(cur){
if(cur->left!=NULL){
pre=cur->left;
while(pre->right){
pre=pre->right;
}
pre->right=cur->right;
cur->right=cur->left;
cur->left=NULL;
}
cur=cur->right;
}
}


思路4 vs 思路3

1
/ \
2   6
/ \   \
3   4   7
/
5


思路三 一步操作之后:

1
\
2
/ \
3   4
/
5
\
6
\
7


思路四 一步操作之后:

1
\
2
/ \
3   4
/ \
5   6
\
7


可以看出,思路四不仅代码简单,效率也比思路三高很多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  algorith tree leetcode