1. 程式人生 > >[LeetCode] Copy List with Random Pointer 拷貝帶有隨機指標的連結串列

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

這道連結串列的深度拷貝題的難點就在於如何處理隨機指標的問題,由於每一個節點都有一個隨機指標,這個指標可以為空,也可以指向連結串列的任意一個節點,如果我們在每生成一個新節點給其隨機指標賦值時,都要去遍歷原連結串列的話,OJ上肯定會超時,所以我們可以考慮用Hash map來縮短查詢時間,第一遍遍歷生成所有新節點時同時建立一個原節點和新節點的雜湊表,第二遍給隨機指標賦值時,查詢時間是常數級。程式碼如下:

解法一:

class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        if (!head) return NULL;
        RandomListNode *res = new RandomListNode(head->label);
        RandomListNode *node = res;
        RandomListNode *cur = head->next;
        map<RandomListNode*, RandomListNode*> m;
        m[head] 
= res; while (cur) { RandomListNode *tmp = new RandomListNode(cur->label); node->next = tmp; m[cur] = tmp; node = node->next; cur = cur->next; } node = res; cur = head; while (node) { node
->random = m[cur->random]; node = node->next; cur = cur->next; } return res; } };

當然,如果使用雜湊表佔用額外的空間,如果這道題限制了空間的話,就要考慮別的方法。下面這個方法很巧妙,具體細節可參見神網友水中的魚的部落格,該方法可以分為以下三個步驟:

1. 在原連結串列的每個節點後面拷貝出一個新的節點

2. 依次給新的節點的隨機指標賦值,而且這個賦值非常容易 cur->next->random = cur->random->next

3. 斷開連結串列可得到深度拷貝後的新連結串列

解法二:

class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        if (!head) return NULL;
        RandomListNode *cur = head;
        while (cur) {
            RandomListNode *node = new RandomListNode(cur->label);
            node->next = cur->next;
            cur->next = node;
            cur = node->next;
        }
        cur = head;
        while (cur) {
            if (cur->random) {
                cur->next->random = cur->random->next;
            }
            cur = cur->next->next;
        }
        cur = head;
        RandomListNode *res = head->next;
        while (cur) {
            RandomListNode *tmp = cur->next;
            cur->next = tmp->next;
            if(tmp->next) tmp->next = tmp->next->next;
            cur = cur->next;
        }
        return res;
    }
};