复杂链表的复刻

暴力做法

时间复杂度 O (n^2)

  1. 遍历一遍,复制 next 指针,新建链表
  2. 遍历第二遍,复制 random 指针,查找每一个 random 节点的位置
class Solution {
public:
    ListNode *copyRandomList(ListNode *head) {
        ListNode* dummy=new ListNode (-1),*tail=dummy;
        if(!head)   return dummy->next;
        //遍历一遍,复制next指针
        for(auto p=head;p;p=p->next)
            tail=tail->next=new ListNode(p->val);
        //遍历第二遍,复制random指针
        tail=dummy->next;
        for(auto p=head;p;p=p->next,tail=tail->next)
            if(p->random)//从头开始寻找random指针指向的地方
            {
                auto t=dummy->next,t2=head;//t和t2分别指向新旧链表
                while(t2!=p->random)//两指针同时往后走,直到找到random
                {
                    t=t->next;
                    t2=t2->next;
                }
                tail->random=t;
            }
        return dummy->next;
    }
};

哈希做法

暴力复杂度主要用于查找 random 节点,我们可以哈希存储原链表和新链表节点的对应关系,实现O (1) 查找

/**
 * Definition for singly-linked list with a random pointer.
 * struct ListNode {
 *     int val;
 *     ListNode *next, *random;
 *     ListNode(int x) : val(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *copyRandomList(ListNode *head) {
        ListNode* dummy=new ListNode (-1),*tail=dummy;
        if(!head)   return dummy->next;
        unordered_map<ListNode*,ListNode*> hashtable;
        //遍历一遍,复制next指针,同时记录新旧链表节点的对应关系
        for(auto p=head;p;p=p->next)
        {
            tail=tail->next=new ListNode(p->val);
            hashtable[p]=tail;
        }
        //遍历第二遍,复制random指针
        tail=dummy->next;
        for(auto p=head;p;p=p->next,tail=tail->next)
            if(p->random)
                tail->random=hashtable[p->random];
                
        return dummy->next;
    }
};

第二种哈希方法

class Solution {
public:
    ListNode *copyRandomList(ListNode *head) {
        unordered_map<ListNode*, ListNode*> hashtable;
        hashtable[nullptr] = nullptr;
        //提前将NULL指针映射,这样当random为NULL时不会分配节点
        auto dummy = new ListNode(-1), tail = dummy;
        while(head)
        {
            if(!hashtable.count(head))  hashtable[head]=new ListNode(head->val);
            if(!hashtable.count(head->random))  
                hashtable[head->random]=new ListNode(head->random->val);
            tail->next=hashtable[head];//tail复制顺序不能变哈
            tail->next->random=hashtable[head->random];
            head=head->next;
            tail=tail->next;
        }
        return dummy->next;
    }
};

取巧方法

/**
 * Definition for singly-linked list with a random pointer.
 * struct ListNode {
 *     int val;
 *     ListNode *next, *random;
 *     ListNode(int x) : val(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *copyRandomList(ListNode *head) {
        if(!head)   return NULL;
        //复制小弟节点
        for(auto p=head;p;p=p->next->next)
        {
            auto t=new ListNode(p->val);
            t->next=p->next;
            p->next=t;
        }
        //复制random节点
        for(auto p=head;p;p=p->next->next)
            if(p->random)//random不空才处理,默认是NULL的
                p->next->random=p->random->next;
        //抽离链表
        ListNode *dummy=new ListNode(head->val),*tail=dummy;
        for(auto p=head;p;p=p->next)
        {
            //将新节点加入新链表
            auto new_node=p->next;
            tail=tail->next=new_node;
            //恢复原链表
            p->next=p->next->next;
        }
        return dummy->next;
    }
};

posted @   穿过雾的阴霾  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示