LeetCode----Copy List with Random Pointer 深度拷贝,浅度拷贝,Lazy拷贝解析


题目: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. 随机只向链表的某一个 node。

题目要求我们给出这个链表的一个 deep copy.

首先,何为 deep copy ??


Part 1: 三种 Object Copy 的对比(以 Array 为例)

1. Shallow copy

拷贝时仅仅复制的是 指针 或者 引用, 也就是说 数据仅存在一份。

当然,得到效率的同时,存在的问题就是,如果原来的数据改变了, 复制后的对象也改变了,因为仅仅存在一份数据!!!

Note: 其实是出于效率的考虑,在某些场合,并不需要多份数据时,可以采用 shallow copy

\

2. Deep copy<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+0+sgc2hhbGxvdyBjb3B5ILK7zayjrGRlZXAgY29weSC4tNbGuvOjrMr9vt3T0Lbgt92ho9LytMujrCBkZWVwIGNvcHkg0rKxyL3Pt9HKsaGjPC9wPgo8cD7U2iBDJiM0MzsmIzQzOyDW0KOsv8nS1NfU0NC2qNLlwOC1xCBjb3B5ILm51Oy6r8r9wLTKtc/WIGRlZXAgY29weS48L3A+CjxwPlB5dGhvbiDW0KOsYXJyYXkgxKzIz7XEuLTWxsrHIHNoYWxsb3cgY29weSwgIL/J0tSyydPDIGNvcHkgxKO/6bXEIGRlZXAgY29weTxicj4KPC9wPgo8cD48aW1nIHNyYz0="http://www.2cto.com/uploadfile/Collfiles/20140128/20140128095635146.jpg" alt="\">

3. Lazy copy

这是一种上述两种策略的组合。又称为 copy-on-write.

最初复制时,采用效率更高的 shallow copy, 同时用一个计数器 counter 记录当前share数据的对象数目。

当需要对数据进行修改时,根据 counter, 采用 deep-copy,

也就是当需要 deep-copy 时,才调用比较费时的 deep-copy.


回归本题:deep copy of the list

对于正常的单链表, 一份 deep copy 非常的容易。只要对链表循环一次,依次复制节点即可。

但是问题的困难在于: Node 多了一个 random 指针域。

对于 random 域:

如果 原链表: Node i 指向 Node j

新链表: Node i 同样指向 Node j(新链表的node)

\

如何能够找到新链表每个节点 random 域 所指向的节点呢??

思路: Step 1: 首先指向在原链表的每个节点后面,复制一个新的节点,原链表长度变为 2 倍

random 指针指向的是 原链表节点 random 指针指向的节点的后面的那个节点

Step 2: 将链表拆成两个 lists

\



/**
 * 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 *tHead = head;
        RandomListNode *next = NULL;
        while(tHead)
        {
            next = tHead->next;
            RandomListNode *node = new RandomListNode(tHead->label);
            node->next = tHead->next;
            //node->random = tHead->random;
            tHead->next = node;
            tHead= next;
        }
        tHead = head;
        while(tHead)
        {
            if(tHead->random) tHead->next->random = tHead->random->next;
            tHead = tHead->next->next;
        }
        RandomListNode *retHead = NULL;
        RandomListNode *tRet = NULL;
        
        tHead = head;
        RandomListNode *next2 = NULL;
        while(tHead)
        {
            if(retHead == NULL)
            {  
                next2 = tHead->next->next;
                retHead = tHead->next;
                tRet = retHead;
                tHead->next = next2;
                tHead = next2;
            }
            else
            {
                next2 = tHead->next->next;
                tRet->next = tHead->next;
                tHead->next = next2;
                tHead = next2;
                tRet = tRet->next;
            }

        }
        return retHead;
    }
};


评论关闭