用哈希表不是最佳答案,最好的方法是原地修改法:
- 复制一个新的节点在原有节点之后,如 1 -> 2 -> 3 -> null 复制完就是 1 -> 1 -> 2 -> 2 -> 3 - > 3 -> null
- 从头开始遍历链表,通过 cur.next.random = cur.random.next 可以将复制节点的随机指针串起来,当然需要判断 cur.random 是否存在
- 将复制完的链表一分为二
图解步骤:
原链表:
首先复制
再处理连接random节点
最后一分为二
/*
// 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) {
CloneNodes(head);
Connectrandom(head);
return Reconnect(head);
}
void CloneNodes(Node* head){
//创建新节点并将新节点连接到原节点后面
Node* node = head;
while(node!=nullptr){
Node* clone = new Node(-1);
//此处不能简单clone = node进行复制,因为两者指向的下一个节点是不同的!
clone->val = node->val;
clone->next = node->next;
clone->random = nullptr;//记得先将random置空,下一步处理
//将克隆结点和原节点都向前移动
node->next = clone;
node = clone->next;
}
}
void Connectrandom(Node* head){
//将原节点的random节点对应在前面复制节点的相应位置进行复制
Node* node = head;
while(node!=nullptr){
Node* clone = node->next;
if(node->random!=nullptr){
clone->random = node->random->next;
}
node = clone->next;
}
}
Node* Reconnect(Node* head){
//将刚才复制的链表拆成两个
Node* node = head;
Node* clonehead = nullptr;
Node* clone = nullptr;
if(node!=nullptr){//获得克隆的头结点
clonehead = clone = node->next;
node->next = clone->next;
node = node->next;
}
while(node!=nullptr){
clone->next = node->next;
clone = clone->next;//克隆节点前移
node->next = clone->next;
node = node->next;//结点前移
}
return clonehead;
}
};