题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),
请对此链表进行深拷贝,并返回拷贝后的头结点。
(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
C++代码
RandomListNode* Clone(RandomListNode* pHead) {
//方法一:遍历两次链表,用map缓存遍历的每个结点
#if 0
unordered_map<RandomListNode*, RandomListNode* >mymap;
//在第一次遍历给定链表的时候,需要复制每个结点值新建结点,
//用map保存新建结点和旧结点成一个键值对
RandomListNode* work = pHead;
//注意输入链表为NULL的特殊情况
if (work == NULL)
mymap.insert({ pHead ,NULL });
while (work != NULL)
{
RandomListNode* newnode = new RandomListNode(work->label);//新建结点
mymap.insert({ work, newnode });//保存新旧结点:注意这个大括号对{}
work = work->next;
}
//第二次遍历链表,根据旧结点的链接关系,给新结点赋予关系
work = pHead;
while (work != NULL)
{
RandomListNode* newnode = mymap.at(work);
//if(work->next==NULL)
/// newnode->next=NULL;
//else
// newnode->next=mymap.at(work->next);
//根据旧结点,映射关系到新结点中去
newnode->next = work->next ? mymap.at(work->next) : NULL;
newnode->random = work->random ? mymap.at(work->random) : NULL;
work = work->next;
}
return mymap.at(pHead);
#endif
//方法二:多次遍历旧链表:需要3次
#if 1
//1、根据旧链表创建新的结点
RandomListNode* cur = pHead;
RandomListNode* next;
while (cur != NULL)
{
next = cur->next;//保留旧链表的下一个结点
RandomListNode* newnode = new RandomListNode(cur->label);
newnode->next = cur->next;
cur->next = newnode;
cur = next;//移到旧链表的下一个结点
}
//2、根据旧链表的结点关系给新结点赋予关系
cur = pHead;
while (cur != NULL)
{
RandomListNode* newnode = cur->next;
if (cur->random == NULL)
{
newnode->random == NULL;
}
else
{
newnode->random = cur->random->next;//在旧结点的下一个结点
}
cur = newnode->next;//cur还是指向旧结点
}
//3、拆分新旧链表
cur = pHead;//旧链表
RandomListNode* head = new RandomListNode(-1);//新链表头
RandomListNode* p = head;
p->next = NULL;
while (cur != NULL)
{
if (cur->label == cur->next->label)//当前结点是旧结点
{
p->next = cur->next;
cur->next = cur->next->next;//指向下一个旧的点
}
cur = cur->next;
p = p->next;
p->next = NULL;//保证结束的时候有链尾结点
}
return head->next;
#endif
}