【剑指Offer-分解让复杂问题简单化】面试题35:复杂链表的复制

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

思路

可以将该问题的求解分为3步:
1、对于原始链表中的每个节点复制该节点放在原节点的后面,如下图

2、设置复制节点的下一个节点。如果原节点N随机指向的节点为S,则N'随机指向的节点为S->next,如下图

3、经过前两步的链表包含了原始节点和复制的节点,这一步将它们分离:原始链表中的节点下标为奇数(下标从1开始),复制后的链表中的节点下标为偶数,如下图

代码如下:

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead==nullptr)
            return nullptr;
        
        /*1、添加复制后的节点*/
        RandomListNode* curNode = pHead;
        while(curNode!=nullptr)
        {
            RandomListNode* clonedNode = new RandomListNode(curNode->label);
            RandomListNode* nextNode = curNode->next;
            curNode->next = clonedNode;
            clonedNode->next = nextNode;
            curNode = nextNode;
        }
        
        /*2、连接随机节点*/
        curNode = pHead;
        while(curNode!=nullptr)
        {
            RandomListNode* clonedNode = curNode->next;
            if(curNode->random!=nullptr)
                clonedNode->random = curNode->random->next;
            curNode = clonedNode->next;
        }
        
        /*3、分离原始链表和复制后的链表*/
        RandomListNode* curRaw = pHead;    //原始链表的头结点
        RandomListNode* clonedHead = pHead->next;    //复制的链表的头结点
        RandomListNode* curCloned = clonedHead;
        /*while(curRaw!=nullptr)    //该方法也可以通过
        {
            curCloned = curRaw->next;
            curRaw->next = curCloned->next;
            if(curCloned->next!=nullptr)
                curCloned->next = curCloned->next->next;
            curRaw = curRaw->next;
        }*/
        
        while(curCloned->next!=nullptr)   //注意终止条件
        {
            curRaw->next = curRaw->next->next;
            curRaw = curRaw->next;
            curCloned->next = curCloned->next->next;
            curCloned = curCloned->next;
        }
        curRaw->next = nullptr;    //使用上面的循环一定要加上这一句,使用注释的循环不需要加
        return clonedHead;
    }
};
posted @ 2020-03-12 17:05  Flix  阅读(158)  评论(0编辑  收藏  举报