题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
思路1:O(n^2)的复杂度 -- 先按next指针创建出新的链表,然后两层循环实现random指针的指向,外层循环是遍历原数组,内层循环是找到外层循环当前节点的random指针所指向的节点。
思路2:O(n)的复杂度
以下面的复杂链表为例:
第一步:仍然是根据原始链表的每个结点N 创建对应的N’。把N’链接在N的后面。图4.8 的链表经过这一步之后的结构,如图4.9 所示。
第二步:设置复制出来的结点的random。假设原始链表上的N的sibling指向结点S,那么其对应复制出来的N’是N的pext指向的结点,同样S’也是S的next指向的结点。设置random之后的链表如图4.10 所示。
第三步:把这个长链表拆分成两个链表。把奇数位置的结点用next .
链接起来就是原始链表,把偶数位置的结点用next 链接起来就是复制
出来的链表。图4. 10 中的链表拆分之后的两个链表如图4.11 所示。
思路1代码:
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
RandomListNode *h, *p, *copy_p;
if(!pHead) return NULL;
h = copy_p = new RandomListNode(pHead->label); //创建头结点
p = pHead->next;
while(p) // 第一次遍历原链表(从原链接头结点后面的那个节点开始遍历)
{
copy_p->next = new RandomListNode(p->label);
copy_p = copy_p->next;
p = p->next;
}
p = pHead;
copy_p = h;
while(p) // 第一次遍历原链表(从原链接头结点开始遍历)
{
int cnt = 0;
RandomListNode* mid = pHead;
while(mid)
{
if(mid==p->random)
break;
mid = mid->next;
++cnt;
}
copy_p->random = findRandom(h, cnt); // 调用函数
p = p->next;
copy_p = copy_p->next;
}
return h;
}
RandomListNode* findRandom(RandomListNode* h, int cnt)
{
RandomListNode* p = h;
for(int i=0; i<cnt; ++i)
p = p->next;
return p;
}
};
思路2代码:
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
RandomListNode *h, *p, *copy_p;
if(!pHead) return NULL;
p = pHead->next;
h = new RandomListNode(pHead->label); // 新建h节点,并符在pHead节点之后
h->next = pHead->next;
pHead->next = h;
//第一次遍历 -- 挂载
while(p)
{
copy_p = new RandomListNode(p->label); //新建节点并符在p指针指向的节点后面
copy_p->next = p->next;
p->next = copy_p;
p = p->next->next; // p指针后移两步
}
// 第二次遍历 实现random指针的指向
p = pHead;
copy_p = h;
while(p)
{
if(p->random) //注意random可能是空指针,这里不要忘了判断一下 --------------- 切记
copy_p->random = p->random->next; //copy_p指针的random指向赋值
p = p->next->next;
if(copy_p->next) // 否则说明copy_p指向最后一个节点 ----------------------- 切记
copy_p = copy_p->next->next; // 不要忘了copy_p指针也后移 ------------- 切记
}
// 第三次遍历 -- 断链
p = pHead;
copy_p = h;
while(p) // 这里这里是判断p 因为下面第三行p指针会后移。
{
p->next = p->next->next;
p = p->next;
if(copy_p->next) // -------------------------------------------------- 切记
{
copy_p->next = copy_p->next->next;
copy_p = copy_p->next;
}
}
return h;
}
};