题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点)。
解题思路(转载自网上):
图 4.8 是一个含有 5 个结点的复杂链表。图中实线箭头表示 next 指针,虚线箭头表示 sibling 指针。为简单起见,指向 null 的指针没有画出。

在不用辅助空间的情况下实现 O(n)的时间效率。
第一步:仍然是根据原始链表的每个结点N 创建对应的 N’。把 N’链接在N的后面。图 4.8 的链表经过这一步之后的结构,如图 4.9 所示。

第二步:设置复制出来的结点的 sibling。假设原始链表上的 N 的 sibling 指向结点 S,那么其对应复制出来的 N’是 N的 pext 指向的结点,同样 S’也是 S 的 next 指向的结点。设置 sibling 之后的链表如图 4.10 所示。

第三步:把这个长链表拆分成两个链表。把奇数位置的结点用 next 链接起来就是原始链表,把偶数位置的结点用 next 链接起来就是复制 出来的链表。图 4.10 中的链表拆分之后的两个链表如图 4.11 所示。

代码实现:
/*
public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
*/
public class Solution {
public RandomListNode Clone(RandomListNode pHead){
CloneNodes(pHead);
ConnectSiblingNodes(pHead);
return ReconnectNodes(pHead);
}
private RandomListNode ReconnectNodes(RandomListNode pHead) {
// TODO Auto-generated method stub
RandomListNode pNode=pHead;
RandomListNode pCloneHead=null;
RandomListNode pCloneNode=null;
if(pNode!=null){
pCloneNode=pCloneHead=pHead.next;
pNode.next=pCloneNode.next;
pNode=pNode.next;
}
while(pNode!=null){
pCloneNode.next=pNode.next;
pCloneNode=pCloneNode.next;
pNode.next=pCloneNode.next;
pNode=pNode.next;
}
return pCloneHead;
}
private void ConnectSiblingNodes(RandomListNode pHead) {
// TODO Auto-generated method stub
RandomListNode pNode = pHead;
while (pNode != null) {
if (pNode.random != null) {
pNode.next.random = pNode.random.next;
}else{
pNode.next.random=null;
}
pNode=pNode.next.next;
}
}
private void CloneNodes(RandomListNode pHead) {
// TODO Auto-generated method stub
RandomListNode pNode=pHead;
while(pNode!=null){
RandomListNode pCloned=new RandomListNode(pNode.label);
pCloned.next=pNode.next;
pNode.next=pCloned;
pNode=pCloned.next;
}
}
}
本文介绍了如何在不使用额外空间的情况下,通过三步法实现复杂链表的克隆,达到O(n)的时间复杂度。包括创建副本节点、设置副本节点的sibling指针和拆分链表。
225

被折叠的 条评论
为什么被折叠?



