转载自https://blog.youkuaiyun.com/linhuanmars/article/details/22463599/
不能一次扫描就生成复制链表,因为随机指针指向的节点可能还没有创建
解法1 :对链表进行两次扫描,第一次顺接生成next值,并将原链表与新链表相应节点作为一对值存入一个map
第二次扫描,根据map得出各节点random指针的指向。
时间复杂度o(n),空间复杂度o(n)
/**
* Definition for singly-linked list with a random pointer.
* struct RandomListNode {
* int label;
* RandomListNode *next, *random;
* RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
* };
*/
#include<cstdlib>
#include<iostream>
#include <map>
using namespace std;
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if (head == NULL)
return head;
map<RandomListNode*, RandomListNode*> mymap;
RandomListNode* newHead = new RandomListNode(head->label);
mymap.insert(pair<RandomListNode*, RandomListNode*>(head, newHead));
RandomListNode* pre = newHead;
RandomListNode* node = head->next;
while (node != NULL)
{
RandomListNode* newNode = new RandomListNode(node->label);
mymap.insert(pair<RandomListNode*, RandomListNode*>(node, newNode));
pre->next = newNode;
pre = newNode;
node = node->next;
}
node = head;
//RandomListNode* copyNode = newHead;
while (node != NULL)
{
mymap[node]->random = mymap[node->random];
node = node->next;
}
return newHead;
}
};
调错总结:
(1)开始用的小写null,显示undefined,加了头文件<cstdlib><iostream>名称空间std还是报错,换成大写NULL解决!
(2)判断为控是判断指针,而不是指针指向的对象,否则报错 == 运算符左右不匹配
(3)开始用HashMap,包含了头文件hash_map还是无法识别该类型,不知道怎么回事,换成map就可以了
STL中关于map, hash_map的方法get, put, insert还得复习一下。
解法2:想避免使用额外空间,只能通过利用链表原来的数据结构来存储节点。基本思路是,对链表进行三次扫描,第一次扫描对每个节点进行复制,然后把复制出的新节点接在原节点的next,也就是让链表变成一个重复链表;第二次把旧节点的随机指针赋给新节点的随机指针,因为新节点都跟在旧节点的下一个,有node.next.random=node.random.next;最后一次扫描把链表拆成两个,第一个还原原链表,第二个就是要求的复制链表,把每隔两个节点分别相连。
时间复杂度o(n),空间复杂度o(1)(因为不需要额外空间)。
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if(head == NULL)
return head;
RandomListNode *node = head, *nextNode = NULL, *pre = NULL;
while(node != NULL)
{
nextNode = node->next;
RandomListNode * newNode = new RandomListNode(node->label);
node->next = newNode;
newNode->next = nextNode;
pre = node;
node = nextNode;
}
RandomListNode *lastNode = new RandomListNode(pre->label);
pre->next = lastNode;
lastNode->next = NULL;
// 第二次扫描,赋random指针值
node = head;
while(node!= NULL)
{
if(node->random!= NULL)
node->next->random = node->random->next;
else
node->next->random = NULL;
node = node->next->next;
}
// 第三次扫描,分类原链表和复制链表(这里写得有些冗余.....)
node = head;
RandomListNode *copyNode = node->next, *copyHead = node->next;
while(node->next->next != NULL)
{
nextNode = node->next->next;
copyNode->next = nextNode->next;
node->next = nextNode;
node = nextNode;
copyNode = node->next;
}
node->next = NULL;
copyNode->next = NULL;
return copyHead;
}
};
调错总结:
member access within null pointer of type 'RandonListNode struct '
原因:如果原链表某节点的随机指针指向的是NULL,则它不在复合链表中,没有下一个节点,复制链表中相应节点的随机指针也该为NULL。