双指针法

双指针法一

  • 克隆节点在原节点后,遍历链表构建随机映射关系,拆分节点。
  • 新链表的随机节点可以通过原链表随机关系获得。
  • 核心:new_cur->random=cur->random->next。
  • 时间/空间: O(n)/O(n)
#include <cstdlib>
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead) {
        if(!pHead) return nullptr;
        RandomListNode* cur=pHead;
        //克隆节点
        while(cur)
        {
            RandomListNode* next=new RandomListNode(cur->label);
            next->next=cur->next;
            cur->next=next;
            cur=cur->next->next;
        }
        //连接random节点
        RandomListNode* ret=pHead->next,*cur1=pHead->next;
        cur=pHead;
        while(cur)
        {
            cur1->random=cur->random?cur->random->next:nullptr;
            cur=cur->next->next;
            if(cur1->next)
            cur1=cur1->next->next;
        }
        //拆分链表
        cur=pHead;
        cur1=ret;
        while(cur)
        {
            cur->next=cur->next->next;
            cur1->next=cur1->next?cur1->next->next:nullptr;
            if(cur) cur=cur->next;
            if(cur1) cur1=cur1->next; 

        }
        return ret;
    }
};

双指针法2

  • 先复制链表,再链接随机节点
  • 利用随机节点间在两个链表具有相同的相对距离关系,用双指针计算出相对距离
  • 时间/空间: O(n^2)/O(n)
/*
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)
        {
            return nullptr;
        }
        RandomListNode* cur=pHead;
        RandomListNode* new_head=new RandomListNode(pHead->label);
        cur=cur->next;
        RandomListNode* new_cur=new_head;
        while(cur)//cur存在
        {
            new_cur->next=new RandomListNode(cur->label);
            cur=cur->next;
            new_cur=new_cur->next;
        }
        new_cur->next=cur;//nullptr;
        // Random
        cur=pHead;
        new_cur=new_head;
        while(cur)
        {   RandomListNode* cur2=pHead;
            int step=0;
            while(cur2!=cur->random)
            {
                cur2=cur2->next;
                step+=1;
            }
            RandomListNode* new_cur2=new_head;
            while(step)
            {
                new_cur2=new_cur2->next;
                step--;
            }
            new_cur->random=new_cur2;
            cur=cur->next;
            new_cur=new_cur->next;
        }
        return new_head;
    }
};

哈希法

  • 通过哈希保存映射关系。
  • 注意遍历哈希的语法糖。
  • 构建链表的cur节点,比原节点位置慢1个。
  • 时间/空间: O(n)/O(n)。
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead) {
        //哈希法
        if(!pHead)
        {
            return nullptr;
        }
        RandomListNode* dumpy=new RandomListNode(-1);
        RandomListNode* cur=pHead;
        RandomListNode* new_cur=dumpy;
        unordered_map<RandomListNode*, RandomListNode*> mp;
        while(cur)
        {
            RandomListNode* next=new RandomListNode(cur->label);
            new_cur->next=next;
            mp[cur]=new_cur->next;
            cur=cur->next;
            new_cur=new_cur->next;
        }//cur为空

        for(auto& [key,value]:mp)
        {
            value->random=!key->random?nullptr:mp[key->random];
        }
        delete dumpy;
        return mp[pHead];
    }
};