2. 解题思路
2.1 映射表
- 建立新旧节点之间的映射表:old->new,来解决复制random指针
2.2 克隆链表
- 创建一个包含新节点的克隆链表:A --> A' --> B --> B' --> C --> C' --> D --> D'
- 关键点:A'的random指针等于A的random指针指向的节点的next节点
3. 算法
3.1 映射表
- 建立新旧节点之间的映射表:old->new
- 遍历链表两次:
- 第一次遍历:构造新链表,只是对新链表的next指针进行赋值,同时建立旧节点和新建节点之间的映射表,此时不对random指针进行赋值
- 第二次遍历:根据映射表的映射关系,对新链表的random指针进行赋值
3.2 克隆链表
- 第一步:遍历原始链表:A --> B --> C --> D,创建一个包含新节点的克隆链表:A --> A' --> B --> B' --> C --> C' --> D --> D',注意此时不对random指针进行赋值
- 第二步:遍历新链表,当遍历到原始链表节点时,对该节点的下一个节点(也就是A和A'的关系)的random指针进行赋值,该random指针指向原始节点的random指针指向的下一个节点
- 第三步:遍历新链表,把新节点从新链表中挑选出来,构成最终的copy链表并返回
4. 实现
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) {
//建立新旧节点之间的映射表:old->new
map<Node*, Node*> table;
//第一次遍历:构造新链表,此时不对random指针进行赋值
Node dummy(-1);
Node *cur = head;
Node *new_cur = &dummy;
for(; cur != NULL; cur = cur->next, new_cur = new_cur->next){
int v = cur->val;
Node *new_node = new Node(v);
table[cur] = new_node; //关键点:建立旧节点指针到新节点指针的映射
new_cur->next = new_node;
}
//第二次遍历:对新链表的random指针进行赋值
cur = head;
new_cur = dummy.next;
for(; cur != NULL; cur = cur->next, new_cur = new_cur->next){
Node *r = cur->random;
Node *new_r = table[r];
new_cur->random = new_r;
}
return dummy.next;
}
};
克隆链表
class Solution {
public:
Node* copyRandomList(Node* head) {
if(!head) return head;
//copy new node and changing new node next pointer to old node next pointer and old node next pointer to new node
Node *newHead = NULL, *l1, *l2;
for(l1 = head; l1 != NULL; l1 = l1->next->next){
l2 = new Node(l1->val, l1->next, NULL);
l1->next = l2;
}
newHead = head->next;
//fixing the random pointer of the cloned list
for(l1= head; l1 != NULL; l1 = l1->next->next){
if(l1->random) l1->next->random = l1->random->next;
}
//changing the next node of both old and new list
for(l1 = head; l1 != NULL; l1 = l1->next){
l2 = l1->next;
l1->next = l2->next;
if(l2->next)l2->next = l2->next->next;
}
return newHead;
}
};