Leetcode刷题地址:https://leetcode-cn.com/problemset/lcof/
题目
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
提示:
-10000 <= Node.val <= 10000
Node.random 为空(null)或指向链表中的节点。
节点数目不超过 1000 。
Solution 1
哈希node和index,比较愚蠢。。。
主要思路是两次遍历链表,用一个map存储每一个结点指针对应的index。第二次遍历时向前或向后增加到对应的index,然后更新random指针。
时间:O(n + n * n/2) -> O(n^2);
空间:O(n)。
Node* copyRandomList(Node* head) {
if (!head) return head;
Node* curr = head;
Node* res = NULL;
Node* tmp = NULL;
map<Node*, int> m;
int j = 0;
while (curr) {
Node* new_node = new Node(curr->val);
m[curr] = j++;
if (!res) {
res = new_node;
tmp = new_node;
} else {
tmp->next = new_node;
tmp = tmp->next;
}
curr = curr->next;
}
tmp = res;
curr = head;
j = 0;
while (curr) {
if (!curr->random) {
tmp->random = NULL;
} else {
int r = m[curr->random];
Node* tmp3 = tmp;
int m = j;
if (r < j) {
m = 0;
tmp3 = res;
}
while (r >= m) {
if (r == m) {
tmp->random = tmp3;
break;
}
m++;
tmp3 = tmp3->next;
}
}
j++;
tmp = tmp->next;
curr = curr->next;
}
return res;
}
结果:
Solution 2
哈希,原始链表的Node和新建链表的Node哈希。
两次遍历,第一次新建链表,并加入Map;第二次更新next和random指针。
时间:O(n);
空间:O(n)。
Node* copyRandomList(Node* head) {
if (!head) return head;
Node* curr = head;
unordered_map<Node*, Node*> m;
while (curr) {
m[curr] = new Node(curr->val);
curr = curr->next;
}
curr = head;
while (curr) {
m[curr]->next = m[curr->next];
m[curr]->random = m[curr->random];
curr = curr->next;
}
return m[head];
}
Solution 3
参考大佬,实在想不到。
拼接再拆分(旋转、跳跃、我不停歇…)。
时间:O(n);
空间:O(1)。
Node* copyRandomList(Node* head) {
if (!head) return head;
Node* curr = head;
// 第一次遍历,新建结点,紧跟着原始链表的每一个结点
while (curr) {
Node* tmp = curr->next;
curr->next = new Node(curr->val);
curr->next->next = tmp;
curr = tmp;
}
// 第二次遍历,更新random指针
curr = head;
Node* new_node = curr->next;
while (curr) {
if (!curr->random) new_node->random = NULL;
else new_node->random = curr->random->next;
curr = curr->next->next;
if (!curr) break;
new_node = new_node->next->next;
}
// 第三次遍历,重新拼接返回新链表
curr = head;
new_node = curr->next;
Node* res = new_node;
while (curr) {
curr->next = new_node->next;
if (!curr->next) {
new_node->next = NULL;
break;
}
new_node->next = curr->next->next;
curr = curr->next;
new_node = new_node->next;
}
return res;
}
结果: