update 138

This commit is contained in:
ShusenTang 2020-02-07 11:36:14 +08:00
parent 5d0c3103db
commit 753be48bef

View File

@ -1,26 +1,31 @@
# [138. Copy List with Random Pointer](https://leetcode.com/problems/copy-list-with-random-pointer/)
# 思路
题目要求深拷贝一个链表,难点就在于如何处理随机指针的问题。
(其实这题和[133. Clone Graph](https://leetcode.com/problems/clone-graph/)拷贝图是类似的都需要用一个HashMap来记录节点与其副本的映射关系。
## 思路一
可以先不管random指针遍历一遍链表并进行拷贝同时用一个HashMap记录节点与其副本的隐射关系。第二次遍历再处理random指针。
## 思路二
也可以采用DFS的思路进行递归拷贝这样就和133. Clone Graph中的DFS解法很类似了。
也可以采用DFS的思路进行递归拷贝这样就和[133. Clone Graph](https://leetcode.com/problems/clone-graph/)拷贝图中的DFS解法很类似了。
## 思路三
## 思路三*
前两种方法都需要开辟一个HashMap如果不允许额外开辟空间呢
我们可以遍历一遍链表然后将每个节点后接上其对应副本节点同样是先不管副本节点的random指针遍历完成后即变成
我们开辟HashMap的目的是在处理副本节点的random指针时能够快速定位原节点random指向的节点的副本节点即原节点到副本节点的映射。那如果我们一开始复制节点的时候将副本节点插入到原节点后面不就实现了原节点到副本节点的映射了吗。
我们可以遍历一遍链表然后将每个节点后紧接上其对应副本节点同样是先不管副本节点的random指针遍历完成后即变成
```
原链表省略random下同:
1 -> 2 -> 3.
将每个节点后接上其对应副本节点:
1 -> 1' -> 2 -> 2' -> 3 -> 3'.
```
然后再遍历一遍处理好副本节点的random指针最后将新的链表拆成新旧两个部分即可。
代码这里就不写了,有兴趣可以去试试。
然后再遍历一遍处理副本节点的random指针最后将新的链表拆成新旧两个部分即可。即一共有三个步骤
1. 复制节点并紧接在源节点后面;
2. 处理random指针
3. 拆分成两个链表
这样就不用开辟额外的空间了,完美。
# C++
## 思路一
@ -77,3 +82,40 @@ public:
}
};
```
## 思路三*
``` C++
class Solution {
public:
Node* copyRandomList(Node* head) {
if (!head) return NULL;
Node *cur = head;
// 1.复制节点并紧接在源节点后面
while (cur) {
Node *t = new Node(cur->val, NULL, NULL);
t->next = cur->next;
cur->next = t;
cur = t->next;
}
// 2. 处理random指针
cur = head;
while (cur) {
if (cur->random) cur->next->random = cur->random->next;
cur = cur->next->next;
}
// 3. 拆分成两个链表
cur = head;
Node *res = head->next;
while (cur) {
Node *t = cur->next;
cur->next = t->next;
if (t->next) t->next = t->next->next;
cur = cur->next;
}
return res;
}
};
```