1. 程式人生 > 其它 >LeetCode: 138. 複製帶隨機指標的連結串列(中等)[DFS, 迭代]

LeetCode: 138. 複製帶隨機指標的連結串列(中等)[DFS, 迭代]

題目描述

給你一個長度為 n 的連結串列,每個節點包含一個額外增加的隨機指標 random ,該指標可以指向連結串列中的任何節點或空節點。

構造這個連結串列的 深拷貝。 深拷貝應該正好由 n 個 全新 節點組成,其中每個新節點的值都設為其對應的原節點的值。新節點的 next 指標和 random 指標也都應指向複製連結串列中的新節點,並使原連結串列和複製連結串列中的這些指標能夠表示相同的連結串列狀態。複製連結串列中的指標都不應指向原連結串列中的節點 。

例如,如果原連結串列中有 X 和 Y 兩個節點,其中 X.random --> Y 。那麼在複製連結串列中對應的兩個節點 x 和 y ,同樣有 x.random --> y 。

返回複製連結串列的頭節點。

用一個由 n 個節點組成的連結串列來表示輸入/輸出中的連結串列。每個節點用一個 [val, random_index] 表示:

val:一個表示 Node.val 的整數。 random_index:隨機指標指向的節點索引(範圍從 0 到
n-1);如果不指向任何節點,則為 null 。 你的程式碼 只 接受原連結串列的頭節點 head 作為傳入引數。

題解

題解1: DFS

將連結串列想象成一張圖。連結串列中每個節點都有 2 個指標(圖中的邊)。因為隨機指標給圖結構添加了隨機性,所以我們可能會訪問相同的節點多次,這樣就形成了環。

  • 當我們遍歷到某個點時,如果我們已經有了當前節點的一個拷貝,我們不需要重複進行拷貝。
  • 如果我們還沒拷貝過當前節點,我們創造一個新的節點,並把該節點放到已訪問字典中
    整體程式碼入下
/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/

class Solution {
private:
    unordered_map<Node*, Node*
> mp; public: Node* copyRandomList(Node* head) {//DFS if(head == nullptr) return nullptr; if(mp.count(head)) return mp[head]; Node* root = new Node(head->val); mp[head] = root; root->next = copyRandomList(head->next); root->random = copyRandomList(head->random); return root; } };

複雜度分析

  • 時間複雜度:O(N),其中 N 是連結串列中節點的數目。
  • 空間複雜度:O(N) 。

題解二: 迭代

第一次遍歷原連結串列拷貝其值和next指標,並記錄進map,再次遍歷原連結串列,拷貝其random指標,此時map中肯定存在其random指標.
我們要將map[it]->random指向it->random對應的新節點. 即:
map[it]->random = map[it->random];

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/

class Solution{
public:
    Node* copyRandomList(Node* head) {//iteration
        if( head == nullptr ){
            return head;
        }
        unordered_map< Node*,Node* > map;
        Node* newhead = new Node( head->val );
        map[head] = newhead;
        auto pre = newhead;
        for(auto it = head->next ; it!=nullptr ; it = it->next ){
            Node* cur = new Node( it->val );
            map[it] = cur;
            pre->next = cur;
            pre = cur;
        }
        for(auto it = head ; it!=nullptr ; it = it->next ){
            map[it]->random = map[it->random];
        }
        return newhead;
    }
};

複雜度分析

  • 時間複雜度:O(N) 。因為我們需要將原連結串列逐一遍歷。
  • 空間複雜度:O(N) 。 我們需要維護一個字典,儲存舊的節點和新的節點的對應。因此總共需要 N 個節點,需要 O(N) 的空間複雜度。

參考

複製帶隨機指標的連結串列
C++ 比之前的複製無向圖還簡單呢