复制带随机指针的链表


深度拷贝:构造一个完全新的链表,即使原链表毁坏,新链表也可以独立使用

方法一,主要难点在random指针,利用Map, 结点地址与结点序号对应

map1:  原链表结点地址 , 结点位置(第几个结点)

map2:  结点位置(第几个结点),新链表结点地址。在代码中这个map实际是用vector实现,因为下标就代表是第几个结点

/**
 * Definition for singly-linked list with a random pointer.
 * struct RandomListNode {
 *     int label;
 *     RandomListNode *next, *random;
 *     RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        if(head == nullptr)
            return nullptr;
        
        map<RandomListNode*,int> node_no;//原链表:结点地址,第几个结点
        vector<RandomListNode*> no_node;//利用vector的下标表示原链表的第几个结点,对应位置上的值就是新链表的结点地址
        RandomListNode* ptr = head;
        int i =0;//第几个结点
        while(ptr)
        {
            node_no[ptr]=i;//地址和结点编号对应起来
            no_node.push_back(new RandomListNode(ptr->label));//结点编号和新链表结点地址对应
            i++;
            ptr = ptr->next;
        }
        no_node.push_back(nullptr);
        
        i = 0;
        ptr = head;
        while(ptr)//将新链表的next和random连接起来
        {
            no_node[i]->next = no_node[i+1];//next链接起来
            if(ptr->random)
            {
                int id = node_no[ptr->random];//得到这个结点的random指向的结点是第几个结点
                no_node[i]->random = no_node[id];
            }
            i++;
            ptr = ptr->next;
        }
        return no_node[0];
    }
};

方法二,不用Map

/**
 * Definition for singly-linked list with a random pointer.
 * struct RandomListNode {
 *     int label;
 *     RandomListNode *next, *random;
 *     RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        if(head == nullptr)
            return nullptr;
        
        RandomListNode* node = head;
        //第一步,将新结点插入到原结点的后面
        while(node)
        {
            RandomListNode* new_node = new RandomListNode(node->label);
            new_node->next = node->next;//新结点指向下一个原结点
            node->next = new_node;//原结点指向自己的拷贝
            node = node->next->next;//移动到下一个原结点
        }
        node = head;
        //第二步,复制random
        while(node)
        {
            //如果原结点的random存在,则新结点的random指向node的random的next。注意这里要加next,不加的话就成了新结点的random指向一个旧结点
            if(node->random)
                node->next->random = node->random->next;
            node = node->next->next;//移动到下一个原结点
        }
        
        //第三步,将新的结点从这个链表脱离出来
        RandomListNode* new_head = head->next;
        node = head;
        while(node)
        {
            RandomListNode* new_node = node->next;//这个结点时新的还未和新链表链接好的结点
            node->next = new_node->next;//注意新旧链表结点的顺序
            if(new_node->next)
                new_node->next = node->next->next;
            node = node->next;
        }
        return new_head;
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值