LeetCode(9):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.

思考

      本题在传统链表节点的结构体内加入了一个random指针,这个指针可以指向链表中的任意节点或者指向NULL,我们需要做的事情是返回该链表的一个深度拷贝。

      关于赋值、浅拷贝、深拷贝不是很清楚的话可以阅读博文《深入C++的拷贝构造和赋值函数》以及《C++类的赋值运算符“=”重载以及深拷贝和浅拷贝》。

      我拿到本题的第一想法是,直接暴力实现......但是这种题一般都会有一个较优的解法,想了一会没有想出来,就直接使用暴力解法了。

      暴力解法就是我们首先创建一个新的链表newH,该链表中各个节点的label以及next是与原链表head对应的,只不过该链表中所有的random指针为NULL。然后我们遍历原链表,并且使用一个tempP指针来寻找原链表中random指针指向的节点,移动tempP的同时移动一个指向新链表的指针tempQ,将tempQ赋给新链表中对应节点的random指针。等到遍历对原始链表遍历完成,那么任务也就完成了。

      给出代码如下:

/**
 * 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* p = head;
        RandomListNode* newH = new RandomListNode(0);
        RandomListNode* q = newH;
        while(p != NULL){
            q->next = new RandomListNode(p->label);
            p = p->next;
            q = q->next;
        }
        p = head;
        q = newH->next;
        while(p != NULL){
            RandomListNode* tempP = head;
            RandomListNode* tempQ = newH->next;
            while(tempP != p->random && p->random != NULL){
                tempP = tempP->next;
                tempQ = tempQ->next;
            }
            if(p->random == NULL){
                q->random == NULL;
            }
            else{
                q->random = tempQ;
            }
            q = q->next;
            p = p->next;
        }
        return newH->next;
    }
};


      关于这种暴力解法我们就不赘述了,下面我们来看看讨论区的大佬们的解法。大佬们为了避免上面代码中的双重while循环,而想到了一个很有趣的idea,就是我们在对新链表的节点进行定义之后,插入到原链表对应的节点后面,然后赋值random指针,最后再把新链表从原链表中抽出。

      代码如下:

class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        if(head == NULL){
            return NULL;
        }
        RandomListNode* p = head;
        while(p != NULL){
            RandomListNode* temp = new RandomListNode(p->label);
            temp->next = p->next;
            p->next = temp;
            p = p->next->next;
        }
        p = head;
        while(p != NULL){
            if(p->random != NULL){
                p->next->random = p->random->next;
            }
            p = p->next->next;
        }
        RandomListNode* newH = new RandomListNode(0);
        p = head;
        RandomListNode* q = newH;
        while(p != NULL){
            q->next = p->next;
            p->next = q->next->next;
            q->next->next = NULL;
            p = p->next;
            q = q->next;
        }
        return newH->next;
    }
};

      暴力解法的运行时间是86ms,运行内存是1900K,而上面这种解法的运行时间是18ms,运行内存是1200K。


      好了,本题的介绍就到这里,大家周末愉快~











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值