Leetcode 138複製帶隨機指標的連結串列
阿新 • • 發佈:2021-02-18
題意
實現 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指向頭節點 構建原連結串列節點和新連結串列節點的鍵值對
- 建立新節點,並向hash表中新增{cur, 新節點}
- cur 指向原連結串列下一個節點
- 構建新連結串列的next指標和random指標
- hash[cur]->next = hash[cur->next]
- 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 指向節點。
演算法流程
- 複製各節點,構建拼接連結串列:
設原連結串列為node1→node2→⋯ ,構建的拼接連結串列如下所示:node1→node1(new) →node2→node2 (new) →⋯ - 構建新連結串列各節點的 random 指向:
當訪問原節點 cur 的隨機指向節點 cur.random 時,對應新節點 cur.next 的隨機指向節點為 cur.random.next 。 - 拆分原 / 新連結串列:
設定 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;
}
};