复杂链表的复制 哈希表以空间换时间O(n)

本文详细解析了复杂链表(包含next和random指针)的复制算法,通过两种方法实现:一是利用哈希表降低时间复杂度至O(n),二是采用三函数法在原链表上操作,达到O(1)空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

题目描述

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

分析:因为链表有两个指针,一个next指针,一个特殊指针,所以我们如果采取暴力的方式,那么我们每次寻找特殊指针的节点都需要O(n)的时间,再配上外面的链表遍历,那么复杂度将达到O(n^2),这是不可以接受的。

优化:1.由于时间很大花费到了特殊指针寻找当前节点的过程中,所以我们如果采用一个哈希表来存储一下原来的节点到现在节点的映射,那么我们的寻找时间将变为O(1),这样一个for遍历就优化好了,时间复杂度为O(n),同时增加了O(n)的空间。

//使用哈希表,用空间来换取时间,时间复杂度为O(n),空间复杂度为O(n)
/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
private:
    map<RandomListNode*,RandomListNode*>Hash;
public:
    Solution()
    {
        Hash.clear();
    }
    ~Solution()
    {
        
    }
    RandomListNode* ConstructMap(RandomListNode* pHead)
    {
        //对原有链表进行遍历并进行哈希表的构建
        if(pHead==nullptr) return nullptr;
        RandomListNode* Org = pHead;
        RandomListNode* pre = nullptr;
        RandomListNode* pNewHead = nullptr;
        while(Org!=nullptr)
        {
            RandomListNode* pNode = new RandomListNode(Org->label);
            Hash.insert(make_pair(Org,pNode));
            Org = Org->next;
            if(pre==nullptr) {
                pre = pNode;
                pNewHead = pNode;
            }
            else {
                pre->next = pNode;
                pre = pNode;
            }
        }
        return pNewHead;
    }
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead==nullptr) return nullptr;
        RandomListNode* newHead = ConstructMap(pHead);
        //得到哈希表,并初步构建起了next指针,下一步是构建特殊指针
        RandomListNode* pNode = pHead;
        RandomListNode* pNewNode = newHead;
        while(pNode!=nullptr)
        {
            //查找特殊指针
            if(pNode->random==nullptr) {
                pNode = pNode->next;
                pNewNode = pNewNode->next;
                continue;
            }
            RandomListNode* This = pNode->random;
            RandomListNode* now = Hash[This];
            pNewNode->random = now;
            pNewNode = pNewNode->next;
            pNode = pNode->next;
        }
        return newHead;
    }
};

2.三函数法   在原链表上进行操作,不需要开辟辅助空间

具体移步:https://blog.youkuaiyun.com/qq_21997625/article/details/84378436

代码:

//不使用额外空间换取时间复杂度,空间复杂度O(1),时间复杂度O(n)
/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    Solution()
    {
        
    }
    ~Solution()
    {
        
    }
    void InsertList(RandomListNode* pHead)
    {
        if(pHead==nullptr) return;
        RandomListNode* pNode = pHead;
        while(pNode!=nullptr)
        {
            RandomListNode* insertListNode = new RandomListNode(pNode->label);
            insertListNode->next = insertListNode->random = nullptr;
            RandomListNode* temp = pNode->next;
            pNode->next = insertListNode;
            insertListNode->next = temp;
            pNode = temp;
        }
    }
    void InsertSpecial(RandomListNode* pHead)
    {
        if(pHead==nullptr) return;
        // 找到每一个偶数节点所指向的特殊节点
        RandomListNode* pNode = pHead;
        while(pNode!=nullptr)
        {
            RandomListNode* pCloned = pNode->next;
            if(pNode->random==nullptr) {
                pNode = pCloned->next;
                pCloned->random = nullptr;
                continue;
            }
            RandomListNode* now = pNode->random;
            pCloned->random = now->next;
            pNode = pCloned->next;
        }
    }
    RandomListNode* subList(RandomListNode* pHead)
    {
        //拆分偶数节点
        if(pHead==nullptr) return nullptr;
        RandomListNode* pNode = pHead;
        RandomListNode* pClonedHead = nullptr;
        RandomListNode* pClonedNode = nullptr;
        if(pNode!=nullptr)
        {
            pClonedHead = pClonedNode = pNode->next;
            pNode->next = pClonedNode->next;
            pNode = pNode->next;
        }
        while(pNode!=nullptr)
        {
            pClonedNode->next = pNode->next;
            pClonedNode = pClonedNode->next;
            pNode->next = pClonedNode->next;
            pNode = pNode->next;
        }
        return pClonedHead;
    }
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead==nullptr) return nullptr;
        //1.在原链表每一个节点后面插一个复制的节点
        InsertList(pHead);
        //2.添加特殊指针
        InsertSpecial(pHead);
        //3.拆分长链表  得到偶数节点的内容
        return subList(pHead);
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值