Copy List with Random Pointer

本文介绍两种深复制带随机指针链表的方法。一种是利用hashMap建立原链表与新链表节点的映射,快速查找已创建节点;另一种是巧妙地在原链表中插入新节点,再调整random指针,最后分离链表。

在这里插入图片描述
解析:题目大意就是深复制链表[即新链表每个节点的指针不能指向原来的空间]
难点:random指针可以随意指向链表的任何一个节点,链表不像顺序存储的数组,可以容易地获取到任意位置上的元素,链表要取到某个节点的值,必须得从头遍历,这也是操作链表的难点所在
分析:
1.新链表当前节点的next指针只有2种状态
①指向新的节点
②指向之前创建的节点
2.新链表当前节点的random指针存在3种状态
①指向新的节点
②指向之前创建的节点
NULL
利用hashMap建立原链表节点新链表对应节点的映射表,以快速查找当前节点的next指针和random指针所指向的节点是否之前已经创建过,如果之前创建过,直接指向创建过的节点,反则反之。
以**1(2)->2(3)->3(1)**为例,括号内为random指针指向的节点:
为了区别原节点和新节点,将新建立值为1的节点即为1’,2->2’,3->3’
在这里插入图片描述

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;

    Node() {}

    Node(int _val, Node* _next, Node* _random) {
        val = _val;
        next = _next;
        random = _random;
    }
};
*/
class Solution {
public:
    Node* copyRandomList(Node* head) {
        map<Node*, Node*> exist; //映射表,存储原链表和新链表的对应节点
        Node* new_head = new Node(-1, NULL, NULL);
        Node* movPtr = new_head;
        while (head != NULL){
            if (exist[head]){
                movPtr->next = exist[head]; //将节点的next指针指向之前建立的对应节点
            }
            else{
                Node* node = new Node(head->val, NULL, NULL);
                movPtr->next = node;
                exist[head] = node; //创建新的节点
            }
            if (head->random != NULL){
                if (exist[head->random]){
                    movPtr->next->random = exist[head->random];
                }
                else{
                    Node* new_node = new Node(head->random->val, NULL, NULL);
                    movPtr->next->random = new_node;
                    exist[head->random] = new_node;
                }
            }
            movPtr = exist[head];
            head = head->next;    
        }
        
        return new_head->next;
    }
};

第二种解法:构思很奇妙
总体思路分为以下3步:以1(2)->2(3)->3(1)为例,括号的为random指针指向的节点:
1.建立next指针:分别拷贝每个节点,并让原节点指向其拷贝节点,拷贝节点指向原节点的下一个节点,即1(2)->1(NULL)->2(3)->2(NULL)->3(1)->3(NULL)
2.建立random指针[关键]:即1(2)->1(2)->2(3)->2(3)->3(1)->3(1)

cur->next->random = cur->random->next;

3.将链表断开为新链表和原链表
4.返回新链表

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;

    Node() {}

    Node(int _val, Node* _next, Node* _random) {
        val = _val;
        next = _next;
        random = _random;
    }
};
*/
class Solution {
public:
    Node* copyRandomList(Node* head) {
        if (!head) return NULL;   
        Node* cur = head;
        while (cur){ //先拷贝具有相同节点值的节点
            Node* t = new Node(cur->val, NULL,  NULL);
            t->next = cur->next;
            cur->next = t;    
            cur = cur->next->next;
        }
        cur = head;
        while (cur){ //random指针赋值
            if (cur->random) cur->next->random = cur->random->next;
            cur = cur->next->next;
        }
        Node* res = head->next;
        cur = head;
        while (cur){ //断开节点
            Node* t = cur->next;
            cur->next = t->next;
            if (t->next) t->next = t->next->next;
            cur = cur->next;
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值