剑指 Offer 35. 复杂链表的复制
个人思路
题意
本题考查的是链表的深拷贝和浅拷贝
ListNode* cur = head //是浅拷贝,cur与head共用一个地址
ListNode* cur = new ListNode()//是深拷贝,二者地址不同
此题的原链表和复制链表中,各自的指针(next和random)指向各自链表内数据的地址
思路
- 先复制next指针,构建出复制链
- 在根据原链中的random,在复制链中构造random
难点在于如何完成深拷贝,如何根据原链的random确定复制链中random的指向
暴力O(n2)
如何完成深拷贝:通过文章开头的new来创建节点
如何根据原链的random确定复制链中random的指向:
- 从头遍历原链
- 记录原链的当前节点的random
- 从头遍历原链,得到random距离头结点的步数
- 在复制链中找到相应步数对应的结点,让random指向它
哈希表——空间换时间O(n)
- 用哈希表mp记录,mp[原链节点]=复制节点
- 从头遍历原链
- 记录原链的当前节点的random
- mp中寻找对应的复制节点
- 复制链的当前节点的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) {
if(head == NULL){
return NULL;
}
//复制next
Node* cur = head;
bool flag = false;//标记是否是复制链的头结点
Node* ans, *pre;
while(cur != NULL){
//创建新节点
Node* temp = new Node(cur->val);
temp->next = NULL;
temp->random = NULL;
if(flag == false){//将复制链的头结点给ans
flag = true;
ans = temp;
pre = ans;
}else{
pre->next = temp;
pre = pre->next;
}
cur = cur->next;
}
//复制random
Node* i = head;
Node* copycur = ans;
while(i != NULL){
Node* rand = i->random;
if(rand == NULL){
copycur->random = NULL;
}else{
//记录原链的random距离头结点有多少步
Node* j = head;
int step = 0;
while(j != NULL){
if(j == rand){
break;
}
step++;
j = j->next;
}
//在复制链中寻找相同的步数
j = ans;
while(step > 0){
j = j->next;
step--;
}
copycur->random = j;
}
i = i->next;
copycur = copycur->next;
}
return ans;
}
};
哈希表
/*
// 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:
unordered_map<Node*, Node*> mp;
Node* copyRandomList(Node* head) {
if(head == NULL){
return NULL;
}
//复制next
Node* cur = head;
Node* pre, *ans;
bool flag = false;
while(cur != NULL){
Node* temp = new Node(cur->val);
mp[cur] = temp;
if(flag == false){
ans = temp;
pre = ans;
flag = true;
}else{
pre->next = temp;
pre = pre->next;
}
cur = cur->next;
}
//通过hash复制random
Node *i = head;
Node *j = ans;
while(i != NULL){
Node* temp = i->random;
if(temp != NULL){
j->random = mp[temp];
}
i = i->next;
j = j->next;
}
return ans;
}
};