牛客网剑指Offer——复杂链表的复制

题目描述

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

概念

复杂链表示例:


方法一

可以分为两步来完成:

1、复制原始链表上的每一个结点,并用next链接起来;

2、设置每个结点的random 指针:由于链表中节点的random指针指向的节点可能在该节点之前,也可能在该节点之后,需要从头到尾的遍历链表来进行查找,然后连接起来,所以时间复杂度是O(N^2)。

方法二

方法一的时间花费主要在定位结点的random上,故我们可以对此优化:用空间换时间。方法还是可以分为两步:

1、复制原始链表上的每一个结点,并用next链接起来,同时创建一个map映射表:<N,N'>(原始结点,复制的结点),将两个链表中的节点映射起来,从而便于后续random指针的设置。

2、设置每个结点的random 指针:由于已经使用map结构将两个链表中的节点进行了映射,可以很方便的找到random指针应该指向的节点。用O(n)的空间消耗把时间复杂度由O(N^2)降到了O(n)。

扫描二维码关注公众号,回复: 153388 查看本文章

对应的代码如下:

/*
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 == NULL )
            return NULL;
        unordered_map<RandomListNode*,RandomListNode*> record;
        RandomListNode* res = new RandomListNode(pHead->label);
        RandomListNode* p1 = pHead->next;
        RandomListNode* p2 = res;
        while( p1 )
        {
            RandomListNode* temp = new RandomListNode(p1->label);
            p2->next = temp;
            record.insert( make_pair(p1,temp) );
            p1 = p1->next;
            p2 = temp;
        }
        p1 = pHead;
        p2 = res;
        while( p1 )
        {
            if( p1->random )
                p2->random = record[p1->random];
            p1 = p1->next;
            p2 = p2->next;
        }
        return res;
    }
};

方法三

方法可以分为三步,以下图中的链表为例:


1、复制原始链表上的每一个结点N,创建对应的N’,并把N’放在N之后。如下图:


2、设置每个结点的random 指针。如果原始链表上的结点N的random指向S,则对应的复制结点N’(即节点N的next)的random指向S’(节点S的next)。如下图:

3、将长链表拆分成两个链表:把奇数位置的结点用pNext连接起来的就是原始链表,把偶数位置的结点通过pNext连接起来的就是复制链表。


代码如下:

/*
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 == NULL )
            return NULL;
        RandomListNode* p = pHead;
        while( p ) //复制每个节点
        {
            RandomListNode* temp = new RandomListNode(p->label);
            temp->next = p->next;
            p->next = temp;
            p = temp->next;
        }
        p = pHead;
        while( p ) //设置random指针
        {
            if( p->random )
                p->next->random = p->random->next;
            p = p->next->next;
        }
        p = pHead;
        RandomListNode* res = pHead->next;
        while( p ) //拆分
        {
            RandomListNode* n = p->next;
            p->next = n->next;
            if( n->next )
                n->next = n->next->next;
            p = p->next;
        }
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_36132127/article/details/80207130