链表格式
通常链表就是一个值,一个next指针,指向后面的节点。
结构体如下:
struct Node{
int val;
struct Node* next;
}
这个题目里的节点多了一个指针,除了指向下一个节点的next指针,还有一个指向这个链表随机一个节点的random指针。
结构体如下:
struct Node{
int val;
struct Node* next;
struct Node* random;
}
普通链表值拷贝
通常我们拷贝链表的时候,进行值拷贝,只用从头开始遍历就可以,因为节点与节点之间的关系已经确定了,每个节点都是指向后面的节点。直接遍历拷贝就可以了。
随机指针链表拷贝
随机链表的拷贝就是要把这个节点与节点之间的指向关系也同时拷贝。
O(n^2)的方法不写了,就是先遍历一遍,每次遍历都在链表中找random的指向的节点。
下面说一个O(n)的方法,就是依次创建节点,每个节点都插入到原链表的结尾。例如本来一个链表是:
1 -> 2 -> 3 -> 4 -> 5 -> NULL
(随机指针没有表示出来,因为不好画)
变成:
1->1'->2->2'->3->3'->4->4'->5->5'->NULL
(新插入的节点都加了单引号来区分)
这样我们发现,假如1
随机指针指向节点3
,那么我们我们让1'
的随机指针指向3
后面的3'
就可以了~因为我们可以通过1->random
直接来访问3
,所以直接让1'->random
= 1->random->next
就可以了。这样就拷贝成功了。
最后一遍把这个新的链表再拿出来~就是让1'->next = 1'->next->next
这样就可以了。
代码如下:
#include <iostream>
using namespace std;
struct RandomListNode{
int label;
RandomListNode *next, *random;
RandomListNode(int x): label(x), next(NULL), random(NULL){}
};
class Solution{
public:
RandomListNode * copyRandomList(RandomListNode *head){
RandomListNode *node;
RandomListNode *loop = head;
if (loop == NULL) {
return NULL;
}
while (loop != NULL) {
node = (RandomListNode*)malloc(sizeof(struct RandomListNode));
node->label = loop->label;
node->next = loop->next;
node->random = NULL;
loop->next = node;
loop = node->next;
}
loop = head;
while (loop != NULL) {
if (loop->random != NULL) {
loop->next->random = loop->random->next;
}
loop = loop->next->next;
}
RandomListNode *copy = head->next;
loop = head;
node = head->next;
while (loop != NULL && node->next != NULL) {
loop->next = loop->next->next;
node->next = node->next->next;
loop = loop->next;
node = node->next;
}
loop->next = NULL;
return copy;
}
};