目录
小声bb:刚开始不熟悉leetcode,看输入看了半天,在想函数之外是怎么写的。。。其实这不重要,你只要知道有这样一个链表,这个链表的节点由三个部分组成,如图:
显然不能单单用普通链表的复制方法去复制这个复杂链表,比如你不可能只写了节点1,就把节点1的random指向还未创造的节点5
solution1 某种一对一的映射关系
假设我们先不管random,按照next创建好一个最基本的普通链表,但接下来要搞random的时候,你怎么去找?用链表的值去找吗?题目也没说链表的值不能相同啊!所以,要创造另外的某种索引,使原链表中的每一个节点都可以对应到新链表中的每一个相应的节点,反之亦然
这种思路给人一种感觉就是,先分配好每个节点的位置,再去“连连看”。怎么连?关键就在于建立正确的映射关系
数组实现
因为我刚开始忘记map这个东东了,于是写了两个数组arr1和arr2,通过相同的索引得到的数组的值就是原链表和新链表中相对应的节点!
/*
// 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 nullptr;
Node* arr1[1005] = {};
Node* arr2[1005] = {};
int length = 0;
Node* newHead = new Node(0);
Node* cur = head;
Node* newCur = newHead;
for(int i = 0; cur != nullptr; i++) {
arr1[i] = cur;
arr2[i] = newCur;
length++;
newCur->val = cur->val;
if(cur->next != nullptr) {
Node* newNode = new Node(0);
newCur->next = newNode;
newCur = newCur->next;
} else {
newCur->next = nullptr;
}
cur = cur->next;
}
cur = head;
newCur = newHead;
while(cur != nullptr) {
for(int i = 0; i < length; i++) {
if(arr1[i] == cur->random) {
newCur->random = arr2[i];
break;
}
}
newCur = newCur->next;
cur = cur->next;
}
return newHead;
}
};
map实现
一样的思想,现成的工具!(while循环里老是忘记写cur = cur->next好想打自己!
/*
// 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 nullptr;
Node* cur = head;
unordered_map<Node*, Node*> map;
while(cur != nullptr) {
Node* newNode = new Node(cur->val);
map[cur] = newNode;
cur = cur->next;
}
cur = head;
while(cur != nullptr) {
map[cur]->next = map[cur->next];
map[cur]->random = map[cur->random];
cur = cur->next;
}
return map[head];
}
};
solution2 拼接+拆分链表
有点抽象,不好想