复杂链表的复制_牛客题霸_牛客网
描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)。 下图是一个含有5个结点的复杂链表。图中实线箭头表示next指针,虚线箭头表示random指针。为简单起见,指向null的指针没有画出。
示例:
输入:{1,2,3,4,5,3,5,#,2,#}
输出:{1,2,3,4,5,3,5,#,2,#}
解析:我们将链表分为两段,前半部分{1,2,3,4,5}为ListNode,后半部分{3,5,#,2,#}是随机指针域表示。
以上示例前半部分可以表示链表为的ListNode:1->2->3->4->5
后半部分,3,5,#,2,#分别的表示为
1的位置指向3,2的位置指向5,3的位置指向null,4的位置指向2,5的位置指向null
如下图:
示例1
输入:
{1,2,3,4,5,3,5,#,2,#}返回值:
{1,2,3,4,5,3,5,#,2,#}
【解法一】哈希存储对应关系
使用哈希表来进行存储旧结点与新结点的对应关系
首先创建一个头结点newhead用来记录返回结果,定义cur指向这个头结点
while访问每一个原结点,clone一个新结点接入cur的next,创建连接新结点之后,使用map来存储旧结点pHead和创建新结点NextNode。
第二步就是要对random指针进行更新,依次遍历map中的元素,
当遍历元素.first->random为nullptr则新结点也为nullptr,即元素.second->random = nullptr
当不为空的时候,例如下图的访问的第一组关系A->A,
则元素.second->random = mp[元素.first->random]
等号的前半部分就是新链表的random更新式子,
后半部分中的元素.first->random就指向了旧链表中的B,但是新链表的random需要指向新链表中的结点,刚好我们的map就是记录了新链表与旧结点之间的对应关系,那么就mp[旧的B] = 新的B;
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead) {
if(pHead == nullptr)return nullptr;
map<RandomListNode*, RandomListNode*> mp;
RandomListNode *newhead = new RandomListNode(-1);
newhead->next = nullptr;
RandomListNode* cur = newhead;
while(pHead)
{
RandomListNode *NextNode = new RandomListNode(pHead->label);
cur->next = NextNode;
mp[pHead] = NextNode; // 使用map来保存旧结点与新接点的对应关系
cur = cur->next;
pHead = pHead->next;
}
for(auto &e : mp) // 遍历map
{
if(e.first->random==nullptr) // 如果当前key的random为nullptr 直接赋值为空即可
e.second->random = nullptr;
else
e.second->random = mp[e.first->random];
// 始终要记得map中存储的是旧结点与新结点之间的关系
}
return newhead->next;
}
};
【解法二】复制拆分
class Solution {
public:
Node* copyRandomList(Node* head) {
if(head==nullptr) return nullptr;
Node* cur = head;
while(cur) // 复制 1->2->3 复制为 1->1->2->2->3->3
{
Node *clone = new Node(cur->val);
clone->next = cur->next;
cur->next = clone;
cur = clone->next;
}
for(cur = head; cur != nullptr; cur=cur->next->next)
{
if(cur->random == nullptr)
cur->next->random = nullptr;
else
cur->next->random = cur->random->next;
}
Node* pre = head, *res = head->next;
cur = head->next;
while(cur->next)
{
pre->next = pre->next->next;
cur->next = cur->next->next;
cur = cur->next;
pre = pre->next;
}
pre->next = nullptr;
return res;
// Node* res = head->next;
// Node* _head = head;
// Node* pre = nullptr;
// for(cur = head->next; cur->next!=nullptr;)
// {
// pre = cur->next;
// cur->next = cur->next->next;
// cur = cur->next;
// _head->next = pre;
// _head = _head->next;
// }
// _head->next = nullptr;
// return res;
}
};
剑指 Offer 35. 复杂链表的复制
/*
// 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==nullptr)return nullptr;
map<Node*, Node*> mp;
Node *newhead = new Node(0);
newhead->next = nullptr;
Node *pre = newhead;
Node *cur = head;
while(cur)
{
Node *clone = new Node(cur->val);
pre->next = clone;
mp[cur] = clone;
pre = pre->next;
cur = cur->next;
}
for(auto &node : mp)
{
if(node.first->random==nullptr)
node.second->random = nullptr;
else
node.second->random = mp[node.first->random];
}
return newhead->next;
}
};