LeetCode[Linked List]: 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.

/**
 * 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) {}
 * };
 */

我的解题思路如下:

  1. 第一次遍历原始链表做两件事:
    1.1 将每一个节点的地址(key)和在链表中的位置(value)组成的key-value插入map,这样之后通过查找random对应的value就可以知道random所指向的节点的位置(下标从0索引);
    1.2 新建并复制每一个节点的label,next和random指针均为NULL,将新建节点的地址依次插入vector,这样之后就可以通过random所指向的节点的位置获取节点的地址。
  2. 第二次遍历原始链表也做两件事:
    2.1 将新建节点通过next指针串联起来成为复制链表;
    2.2 对于每一个原始节点:在map中查找该节点的random所指向的节点的位置,通过该位置在vector中得到新建链表中对应节点的地址,将该地址赋给复制节点的random即可。

代码实现如下:

    RandomListNode *copyRandomList(RandomListNode *head) {
        if (!head) return head;

        map<RandomListNode *, int> positions;
        vector<RandomListNode *> cpyList;

        int pos = 0;
        for (RandomListNode *curr = head; curr != NULL; curr = curr->next, ++pos) {
            positions.insert(pair<RandomListNode *, int> (curr, pos));
            RandomListNode *newNode = new RandomListNode(curr->label);
            cpyList.push_back(newNode);
        }
        cpyList.push_back(NULL);

        pos = 0;
        for (RandomListNode *curr = head; curr != NULL; curr = curr->next, ++pos) {
            cpyList[pos]->next   = cpyList[pos + 1];
            cpyList[pos]->random = curr->random ? cpyList[positions[curr->random]] : NULL;
        }

        return cpyList[0];
    }


上面代码的时间复杂度是O(N),空间复杂度是O(N)
Discuss上寻求更好的解法,看到一个空间复杂度为O(1)的解法,构思非常巧妙:

  1. 每一个原始链表的节点后面新建一个拷贝节点,e.g. 1->2->3变为1->1->2->2->3->3此时拷贝节点的random均为NULL
  2. 将拷贝节点的random指向正确的位置。
  3. 将链表拆开成为两条链表,返回拷贝链表。

具体代码实现如下:

    RandomListNode *copyRandomList(RandomListNode *head) {
        if(head == NULL) return NULL;

        RandomListNode *p = head;
        while(p != NULL) {
            RandomListNode *q = p->next;
            p->next = new RandomListNode(p->label);
            p->next->next = q;
            p = q;
        }

        for (p = head; p != NULL; p = p->next->next)
            p->next->random = (p->random == NULL) ? NULL : p->random->next;

        p = head;
        RandomListNode *r = head->next;
        for(RandomListNode *q = r;;) {
            p->next = q->next;
            p = p->next;
            if(p == NULL) break;
            q->next = p->next;
            q = q->next;
        }

        return r;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值