题目:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
思路:
思路一:先复制原始链表的每个节点,然后设置每个节点的m_pSibling指针。这样寻找每个节点的m_pSibling节点时都要从头遍历,时间复杂度为O(n^2).
思路二:(优化,空间换时间),先复制原始链表,同时把<N,N'>的配对信息放到一个哈希表中,然后设置m_pSibling时直接从哈希表中取出数据,,这样可以用O(1)的时间找到对应节点。
思路三:(优化,不使用多余空间)。分为三部分
1、复制原始链表的任意节点N并创建新的节点N',再把N'链接到N的后面
2、如果原始链表上的节点N的m_pSibling指向S, 则它对应的复制节点N‘的m_pSibling指向复制的节点S'
3、 把第二步得到的链表拆分成两个链表, *奇数位置上的节点组成原始链表,偶数位置上的节点组成复制出来的链表
代码如下:
/*
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) {
cloneNode(pHead);
connectSiBlingNodes(pHead);
return reConnectNodes(pHead);
}
/**
* 复制原始链表的任意节点N并创建新的节点N',再把N'链接到N的后面
* @param root
*/
public void cloneNode(RandomListNode root){
RandomListNode pNode=root;
while(pNode!=null){
RandomListNode pCloned=new RandomListNode(0);
pCloned.label=pNode.label;
pCloned.next=pNode.next;
pCloned.random=null;
pNode.next=pCloned;
pNode=pCloned.next;
}
}
/**
* 如果原始链表上的节点N的m_pSibling指向S,
* 则它对应的复制节点N‘的m_pSibling指向复制的节点S'
* @param root
*/
public void connectSiBlingNodes(RandomListNode root){
RandomListNode pNode=root;
while(pNode!=null){
RandomListNode pCloned=pNode.next;
if(pNode.random!=null){
pCloned.random=pNode.random.next;
}
pNode=pCloned.next;
}
}
/**
* 把第二步得到的链表拆分成两个链表,
* 奇数位置上的节点组成原始链表,偶数位置上的节点组成复制出来的链表
* @param root
* @return
*/
public RandomListNode reConnectNodes(RandomListNode root){
RandomListNode pNode=root;
RandomListNode pClonedHead=null;
RandomListNode pClonedNode=null;
if(pNode!=null){
pClonedHead=pClonedNode=pNode.next;
pNode.next=pClonedNode.next;
pNode=pNode.next;
}
while(pNode!=null){
pClonedNode.next=pNode.next;
pClonedNode=pClonedNode.next;
pNode.next=pClonedNode.next;
pNode=pNode.next;
}
return pClonedHead;
}
}
注意点:不要忽略最后一步分割链表的时候,除了复制链表还有原链表也要保证不变。