这道题应该是链表中少有的几道需要动脑子的题目之一,在剑指offer上详尽的讲解。用的方法还挺巧妙的。
为了在O(N)的时间内完成复制,就不能每次都查找节点的random指针指向的位置,解法是把复制过程拆成三个步骤。先从把源链表复制一份,复制出的每个节点都连接到原来的节点的后面,然后,复制源链表的每个节点的random指针,最后,把复制后的整个链表从源链表上拆下来。
说一下我实现时遇到的两个问题,第一个是复制后的random指针应该指向源节点的random指针的后面一个节点,但是源链表的random可能是NULL,需要先判空,再操作。另一个错误更愚蠢,为了让代码更简短,我想把上面的第二步和第三步同时完成,结果出了很多RE,原因是random可能指向的是前面的节点,我如果在一个循环里面把它拆了下来,肯定找不到他的下一个节点了啊。。
ac代码如下:
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if(!head)
return NULL;
RandomListNode *pNode = head;
while(pNode){
RandomListNode *newNode = new RandomListNode(pNode->label);
newNode->next = pNode->next;
pNode->next = newNode;
pNode = newNode->next;
}
pNode = head;
RandomListNode *newPNode, *newHead = head->next;
while(pNode){
newPNode = pNode->next;
if(pNode->random)
newPNode->random = pNode->random->next;
pNode = newPNode->next;
}
pNode = head;
while(pNode){
newPNode = pNode->next;
pNode->next = newPNode->next;
pNode = newPNode->next;
if(pNode)
newPNode->next = pNode->next;
}
return newHead;
}
};