LeetCode/solutions/138. Copy List with Random Pointer.md
2019-08-08 16:31:16 +08:00

80 lines
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [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解法很类似了。
## 思路三
前两种方法都需要开辟一个HashMap如果不允许额外开辟空间呢
我们可以遍历一遍链表然后将每个节点后接上其对应副本节点同样是先不管副本节点的random指针遍历完成后即变成
```
原链表省略random下同:
1 -> 2 -> 3.
将每个节点后接上其对应副本节点:
1 -> 1' -> 2 -> 2' -> 3 -> 3'.
```
然后再遍历一遍处理好副本节点的random指针最后将新的链表拆成新旧两个部分即可。
代码这里就不写了,有兴趣可以去试试。
# C++
## 思路一
``` C++
class Solution {
public:
Node* copyRandomList(Node* head) {
if(!head) return NULL;
unordered_map<Node*, Node*>mp;
Node *head_cp = new Node(head -> val);
mp[head] = head_cp;
Node *p1 = head_cp, *p2 = head -> next;
while(p2){
p1 -> next = new Node(p2 -> val);
mp[p2] = p1 -> next;
p1 = p1 -> next; p2 = p2 -> next;
}
p1 -> next = NULL;
p1 = head_cp; p2 = head;
while(p2){
p1 -> random = mp[p2 -> random];
p1 = p1 -> next; p2 = p2 -> next;
}
return head_cp;
}
};
```
## 思路二
``` C++
class Solution {
private:
Node* DFS(Node *node, unordered_map<Node*, Node *>&mp){
if(!node) return NULL;
if(mp.count(node)) return mp[node];
else{
Node *node_cp = new Node(node -> val);
mp[node] = node_cp;
node_cp -> next = DFS(node -> next, mp);
node_cp -> random = DFS(node -> random, mp);
return node_cp;
}
}
public:
Node* copyRandomList(Node* head) {
if(!head) return NULL;
unordered_map<Node*, Node*>mp;
return DFS(head, mp);
}
};
```