题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
我的代码,思路比较笨,就是首先构造一个正常的不大random指针的链表,然后再去遍历原始链表,查看random指针指向的位置,同时移动复制的链表的next,找到后赋值。时间复杂度比较大O(n^2)
public class Solution {
public RandomListNode Clone(RandomListNode pHead)
{
RandomListNode head2 = null ;
RandomListNode cur = head2;
RandomListNode tmp = pHead;
while(tmp!=null){
RandomListNode node = new RandomListNode(tmp.label);
if(cur == null)
cur = head2 = node;
else
{
cur.next = node;
cur = node;
}
tmp = tmp.next;
}
cur = head2;
tmp = pHead;
while(cur!=null){
RandomListNode tmp1 = pHead;
RandomListNode tmp2 = head2;
while(tmp.random != tmp1&&tmp1!=null){
tmp1 = tmp1.next;
tmp2 = tmp2.next;
}
tmp = tmp.next;
cur.random = tmp2;
cur = cur.next;
}
return head2;
}
}
优秀代码,c++写的,忽略语言,看疗效,首先将复制的节点插入到对应的原始节点的后面,这样组成了一个复制节点和原始节点混合的链表,此时链表上除了原始链表节点上的random有指向外,新生成的节点random均为空。下一步就是补齐random节点,利用新旧节点混合在一起的优势,可以很快找到新节点的random指针的指向。最后,没隔一个拆分开。得到原始节点。时间复杂度O(n)。画了张图,将就着看吧。找到红色的random指向后,绿色的也就很容易找到了。
class Solution {
public:
/*
1、复制每个节点,如:复制节点A得到A1,将A1插入节点A后面
2、遍历链表,A1->random = A->random->next;
3、将链表拆分成原链表和复制后的链表
*/
RandomListNode* Clone(RandomListNode* pHead)
{
if(!pHead) return NULL;
RandomListNode *currNode = pHead;
while(currNode){
RandomListNode *node = new RandomListNode(currNode->label);
node->next = currNode->next;
currNode->next = node;
currNode = node->next;
}
currNode = pHead;
while(currNode){
RandomListNode *node = currNode->next;
if(currNode->random){
node->random = currNode->random->next;
}
currNode = node->next;
}
//拆分
RandomListNode *pCloneHead = pHead->next;
RandomListNode *tmp;
currNode = pHead;
while(currNode->next){
tmp = currNode->next;
currNode->next =tmp->next;
currNode = tmp;
}
return pCloneHead;
}
};