1. 程式人生 > 其它 >Leetcode 138複製帶隨機指標的連結串列

Leetcode 138複製帶隨機指標的連結串列

技術標籤:題解分享資料結構leetcode連結串列

題意

實現 copyRandomList 函式,複製一個複雜連結串列。在複雜連結串列中,每個節點除了有一個 next 指標指向下一個節點,還有一個 random 指標指向連結串列中的任意節點或者 null。

示例:

在這裡插入圖片描述

輸入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
輸出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

本題的難點在於如何構建新連結串列的random指標

方法一:雜湊表

利用雜湊表的查詢特點,考慮構建 原連結串列節點 和 新連結串列對應節點 的鍵值對對映關係,再遍歷構建新連結串列各節點的 next 和 random 引用指向即可。

演算法流程:

  • 若head為null, 返回null
  • 初始化:雜湊表hash,cur指向頭節點 構建原連結串列節點和新連結串列節點的鍵值對
    1. 建立新節點,並向hash表中新增{cur, 新節點}
    2. cur 指向原連結串列下一個節點
  • 構建新連結串列的next指標和random指標
    1. hash[cur]->next = hash[cur->next]
    2. hash[cur]->random = hash[cur->random]
  • 返回新連結串列的頭,hash[head]->next;

時間複雜度分析

  • 時間複雜度O(N):兩輪遍歷連結串列
  • 空間複雜度O(N):hash表額外使用O(N)空間

程式碼實現

Node* copyRandomList(Node* head) {
        if(!head) return NULL;
        unordered_map<Node *, Node *> hash;
        Node *cur = head;
        while(cur)
        {
            hash[cur] = new Node(cur->val);
            cur = cur->next;
        }
        cur = head;
        while
(cur) { hash[cur]->next = hash[cur->next]; hash[cur]->random = hash[cur->random]; cur = cur ->next; } return hash[head]; }

方法二: 拼接+拆分

考慮構建 原節點 1 -> 新節點 1 -> 原節點 2 -> 新節點 2 -> …… 的拼接連結串列,如此便可在訪問原節點的 random 指向節點的同時找到新對應新節點的 random 指向節點。

演算法流程

  1. 複製各節點,構建拼接連結串列:
    設原連結串列為node1→node2→⋯ ,構建的拼接連結串列如下所示:node1→node1(new) →node2→node2 (new) →⋯
  2. 構建新連結串列各節點的 random 指向:
    當訪問原節點 cur 的隨機指向節點 cur.random 時,對應新節點 cur.next 的隨機指向節點為 cur.random.next 。
  3. 拆分原 / 新連結串列:
    設定 pre / cur 分別指向原 / 新連結串列頭節點,遍歷執行 pre.next = pre.next.next 和 cur.next = cur.next.next 將兩連結串列拆分開。
複雜度分析:

時間複雜度 O(N): 三輪遍歷連結串列,使用 O(N) 時間。
空間複雜度 O(1) : 節點引用變數使用常數大小的額外空間。

class Solution {
public:
    Node* copyRandomList(Node* head) {
        Node *cur = head;
        while(cur)
        {
            auto next = cur->next;
            auto p = new Node(cur->val);
            p->next = cur->next;
            cur->next = p;
            cur = next;
        }
        cur = head;
        while(cur)
        {
            if(cur->random)
                cur->next->random = cur->random->next;
            cur = cur->next->next;
        }
        cur = head;
        Node *dummy = new Node(-1);
        Node *res = dummy;
        while(cur)
        {
            auto p = cur->next;
            cur->next = p->next;
            res->next = p;
            res = p;
            cur = p->next;
            p->next = NULL; 
        }
        return dummy->next;
    }
};