Copy List with Random Pointer的解题报告

题目要求:

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.

Return a deep copy of the list.

题目就是让你复制一个单链表,但是该链表有一个特殊的地方,每个节点含有一个随机指针,可能指向任何一个节点,这是题目的难点。

解题思路:最常规的方法应该是利用map关联容器。将原节点和复制节点关联起来,然后通过map的关联关系,将原链表中的随机指针复制进复制链表中。以下是代码,大概思路是先生成一个与原链表相同的只有next指针的单链表,并且将新旧节点关联起来,然后在遍历一遍原链表,将随机指针复制进去。

/**
 * 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) {
        RandomListNode *original=head;
        if(head==NULL)return NULL;
        RandomListNode *newlist;
        map<RandomListNode*,RandomListNode*> mark;
        RandomListNode *newnode=new RandomListNode(0);
        newnode->label=head->label;
        newlist=newnode;
        mark.insert(make_pair(head,newlist));
        while(original->next!=NULL)
        {
            newnode=new RandomListNode(0);
            newlist->next=newnode;
            original=original->next;
            newlist=newlist->next;
            newlist->label=original->label;
            mark.insert(make_pair(original,newlist));
        }
        original=head;
        while(original!=NULL)
        {
            mark[original]->random=mark[original->random];
            original=original->next;
        }
        return mark[head];
    }
};
除了这个方法以外,还有一个更巧妙的算法,这个方法 不用保存原始链表的映射关系,构建新节点时,指针做如下变化,即把新节点插入到相应的旧节点后面:

 
 
同理分两步
 
1、构建新节点random指针:new1->random = old1->random->next, new2->random = NULL, new3->random = NULL, new4->random = old4->random->next
 
2、恢复原始链表以及构建新链表:例如old1->next = old1->next->next,  new1->next = new1->next->next
 
该算法时间复杂度O(N),空间复杂度O(1).
以下是代码:
/**
 * 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 == NULL) return NULL;
        RandomListNode *pos1 = head, *pos2 = head->next;
        while (pos1 != NULL) {
            pos1->next = new RandomListNode(pos1->label);
            pos1->next->next = pos2;
            pos1 = pos2;
            if (pos2 != NULL)
                pos2 = pos2->next;
        }
        pos1 = head;  pos2 = head->next;
        while (pos1 != NULL) {
            if (pos1->random == NULL) {
                pos2->random = NULL;
            } else {
                pos2->random = pos1->random->next;
            }
            pos1 = pos1->next->next;
            if (pos2->next != NULL)
                pos2 = pos2->next->next;
        }
        RandomListNode *res = head->next;
        pos1 = head; pos2 = head->next;
        while(pos2->next != NULL) {
            pos1->next = pos2->next;
            pos1 = pos2;
            if (pos2->next != NULL)
                pos2 = pos2->next;
        }
        pos1->next = NULL;
        pos2->next = NULL;
        return res;
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值