1.使用map
如果按照正常的链表复制那样做,由于存在随机节点,可能会出现环,
所以,使用map存在每一个节点与其随机指针的指向,
然后遍历map,复制链表
代码如下:
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
if (head == nullptr)
return head;
//遍历原链表 创建新链表节点并建立映射关系
unordered_map<Node*, Node*> map; //key: 原链表节点 value: 新创建节点
Node* cur = head;
while (cur)
{
map[cur] = new Node(cur->val);
cur = cur->next;
}
//遍历原链表 根据map找新链表的random
cur = head;
while (cur)
{
map[cur]->next = map[cur->next];
map[cur]->random = map[cur->random];
cur = cur->next;
}
return map[head];
}
};
2.原地算法
该算法的步骤大致如下:
1)复制一个新的节点在当前节点之后,如2->4->5->NULL复制完为2->2->4->4->5->5->NULL
2)从头结点开始,将增加的节点的随机指针串起来,cur->next->random=cur->random->next,需要判断cur->random是否存在
3)将复制完的链表一分为2,抽取出第一步新增的所有节点
代码如下:
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
if (head == nullptr)
return head;
//遍历原链表,遍历过程中插入新副本节点
Node* cur = head;
while (cur)
{
Node *node=new Node(cur->val);
Node *next=cur->next;
node->next=next;
cur->next=node;
cur=next;
}
//遍历原链表 对新副本节点设置random指针
cur = head;
while (cur)
{
cur->next->random=cur->random?cur->random->next:NULL;
cur=cur->next->next;
}
cur =head;
Node *new_cur=head->next;
Node *res=new_cur;
while(cur)
{
cur->next=cur->next->next;
cur=cur->next;
new_cur->next=cur?cur->next:NULL;
new_cur=new_cur->next;
}
return res;
}
};