深度拷贝:构造一个完全新的链表,即使原链表毁坏,新链表也可以独立使用
方法一,主要难点在random指针,利用Map, 结点地址与结点序号对应
map1: 原链表结点地址 , 结点位置(第几个结点)
map2: 结点位置(第几个结点),新链表结点地址。在代码中这个map实际是用vector实现,因为下标就代表是第几个结点
/**
* Definition for singly-linked list with a random pointer.
* struct RandomListNode {
* int label;
* RandomListNode *next, *random;
* RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
* };
*/
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if(head == nullptr)
return nullptr;
map<RandomListNode*,int> node_no;//原链表:结点地址,第几个结点
vector<RandomListNode*> no_node;//利用vector的下标表示原链表的第几个结点,对应位置上的值就是新链表的结点地址
RandomListNode* ptr = head;
int i =0;//第几个结点
while(ptr)
{
node_no[ptr]=i;//地址和结点编号对应起来
no_node.push_back(new RandomListNode(ptr->label));//结点编号和新链表结点地址对应
i++;
ptr = ptr->next;
}
no_node.push_back(nullptr);
i = 0;
ptr = head;
while(ptr)//将新链表的next和random连接起来
{
no_node[i]->next = no_node[i+1];//next链接起来
if(ptr->random)
{
int id = node_no[ptr->random];//得到这个结点的random指向的结点是第几个结点
no_node[i]->random = no_node[id];
}
i++;
ptr = ptr->next;
}
return no_node[0];
}
};
方法二,不用Map
/**
* Definition for singly-linked list with a random pointer.
* struct RandomListNode {
* int label;
* RandomListNode *next, *random;
* RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
* };
*/
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if(head == nullptr)
return nullptr;
RandomListNode* node = head;
//第一步,将新结点插入到原结点的后面
while(node)
{
RandomListNode* new_node = new RandomListNode(node->label);
new_node->next = node->next;//新结点指向下一个原结点
node->next = new_node;//原结点指向自己的拷贝
node = node->next->next;//移动到下一个原结点
}
node = head;
//第二步,复制random
while(node)
{
//如果原结点的random存在,则新结点的random指向node的random的next。注意这里要加next,不加的话就成了新结点的random指向一个旧结点
if(node->random)
node->next->random = node->random->next;
node = node->next->next;//移动到下一个原结点
}
//第三步,将新的结点从这个链表脱离出来
RandomListNode* new_head = head->next;
node = head;
while(node)
{
RandomListNode* new_node = node->next;//这个结点时新的还未和新链表链接好的结点
node->next = new_node->next;//注意新旧链表结点的顺序
if(new_node->next)
new_node->next = node->next->next;
node = node->next;
}
return new_head;
}
};