您的位置:首页 > 其它

49. 3种方法实现复杂链表的复制[clone of complex linked list]

2014-05-23 11:55 603 查看
【本文链接】

/article/5268940.html

【题目】

有一个复杂链表,其结点除了有一个next指针指向下一个结点外,还有一个sibling指向链表中的任一结点或者NULL。其结点的C++定义如下:

C++ Code
1
2
3
4
5
6
7

// complex node struct

struct ComplexNode

{

int value;

ComplexNode *next;

ComplexNode *sibling;

};

下图是一个含有5个结点的该类型复杂链表。图中实线箭头表示next指针,虚线箭头表示sibling指针。为简单起见,指向NULL的指针没有画出。



请完成函数ComplexNode* Clone(ComplexNode* pHead),以复制一个复杂链表。

分析】

在常见的数据结构上稍加变化,这是一种很新颖的面试题。要在不到一个小时的时间里解决这种类型的题目,我们需要较快的反应能力,对数据结构透彻的理解以及扎实的编程功底。

分为2步:

(1)复制每一个节点,连接next,初步生成【新链表】,时间复杂度为T(n)=O(1)*n=O(n);

(2)连接sibling,假设在【新链表】中定位sibling的时间复杂度为T,则总的时间复杂度为T(n)=T*n;

由此可见,最为关键的是如何在【新链表】中快速定位sibling节点

【方法1】

统计从头结点该sibling节点的步长step。

假设【原始链表】中的某节点N的sibling指向结点S。由于S的位置在链表上有可能在N的前面也可能在N的后面,所以要定位N的位置我们需要从原始链表的头结点开始找。假设从【原始链表】的头结点开始经过step步找到结点S。那么在【新链表】上从头结点开始经过step可以到结点N'的sibling对应的结点S'。定位sibling的时间复杂度为T=O(n) 。总的时间复杂度O(n2),空间复杂度为O(1)

【方法2】

使用map映射记录<A,A'>,<B,B'>,<C,C'>,这样定位sibling的时间复杂度为T=O(1) 。总的时间复杂度O(n),但是空间复杂度为O(n),相当与以O(n)的空间消耗实现了O(n)的时间效率。

【方法3】

根据原始链表的每个结点N,创建对应的N'。让后将N和N'连接起来,这样定位sibling的时间复杂度为T=O(1) ,之后重新分成2个链表即可。总的时间复杂度O(n),空间复杂度为O(1)

(1)创建新节点,并连接next。



(2)定位sibling并连接。



(3)链表拆分成两个:把奇数位置的结点链接起来就是原始链表,把偶数位置的结点链接出来就是复制出来的链表。



【代码】

C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

// complex node struct

struct ComplexNode

{

int value;

ComplexNode *next;

ComplexNode *sibling;

};

//Clone all nodes in a complex linked list with pHead,

//and connect all nodes with next link.

void CloneNodes(ComplexNode *pHead)

{

// A-A'-B-B'-C-C'

if(NULL == pHead)

return;

ComplexNode *pNode = pHead;

while(pNode != NULL)

{

ComplexNode *pNewNode = new ComplexNode();

pNewNode->value = pNode->value;

pNewNode->next = pNode->next;

pNewNode->sibling = NULL; // init NULL

// connect pNode and pNewNode

pNode->next = pNewNode;

//move to next node

pNode = pNewNode->next;

}

}

//Connect sibling nodes in a complex link list

void ConnectSiblingNodes(ComplexNode *pHead)

{

// A-A'-B-B'-C-C'

if(NULL == pHead)

return;

ComplexNode *pNode = pHead;

while(pNode != NULL)

{

ComplexNode *pNewNode = pNode->next;

// connect sibling nodes

if(pNode->sibling != NULL)

pNewNode->sibling = pNode->sibling->next;

else

pNewNode->sibling = NULL;

}

}

// Split a complex list into two:

// Reconnect nodes to get the original list, and its cloned list

ComplexNode *ReconnectNodes(ComplexNode *pHead)

{

// A-A'-B-B'-C-C'

if(NULL == pHead)

return;

ComplexNode *pNode = pHead;

ComplexNode *pNewHead = pHead->next;

ComplexNode *pNewNode = pNewHead;

while(pNode != NULL)

{

// reconnect next nodes for pNode

pNode->next = pNewNode->next;

// move pNode to next

pNode = pNewNode->next;

// reconnect next nodes for pNewNode

if(pNode != NULL)

{

pNewNode->next = pNode->next;

pNewNode = pNode->next;

}

else

{

pNewNode->next = NULL;

pNewNode = NULL;

}

}

return pNewHead;

}

ComplexNode *Clone(ComplexNode *pHead)

{

CloneNodes(pHead);

ConnectSiblingNodes(pHead);

return ReconnectNodes(pHead);

}

【参考】

http://zhedahht.blog.163.com/blog/static/254111742010819104710337/

/article/6650122.html

【本文链接】

/article/5268940.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: