前言
以專題的形式更新刷題貼,歡迎跟我一起學習刷題,相信我,你的堅持,絕對會有意想不到的收穫。每道題會提供簡單的解答,如果你有更優雅的做法,歡迎提供指點,謝謝。
注:如果程式碼排版出現了問題麻煩通知我下,謝謝。
【題目描述】
【要求】
如果連結串列的長度為 N, 時間複雜度達到 O(N)。
【難度】
尉:★★☆☆
【解答】
方法一:使用額外的儲存空間
這道題的難點在於我們需要定位好隨機指標,一個比較簡單的解法就是把原節點與複製的節點關聯起來,可以使用雜湊表把他們關聯起來。
首先把副節點全部建立出來,然後把原節點與對應的副節點用雜湊表關聯起來。關聯的時候原節點作為key,副節點作為value。例如對於連結串列 1->2->3->null。建立副節點 1', 2', 3'。然後用雜湊表關聯起來:
key | value |
---|---|
1 | 1' |
2 | 2' |
3 | 3' |
之後在把所有副節點連線成一個連結串列。在連線的時候,我們 可以通過雜湊表很容易這找到對應的隨機節點。
程式碼如下
//方法1:採用雜湊表
public static Node1 copyListWithRand(Node1 head) {
Map<Node1, Node1> map = new HashMap<>();
Node1 cur = head;
while (cur != null) {
map.put(cur, new Node1(cur.value));
cur = cur.next;
}
//把副節點連線起來
cur = head;
while (cur != null) {
map.get(cur).next = map.get(cur.next);
map.get(cur).rand = map.get(cur.rand);
cur = cur.next;
}
return map.get(head);
}
這種方法的時間複雜度為 O(n), 空間複雜度也為 O(n)。
方法2
其實我們也可以不需要雜湊表來輔助,也就是說 ,我們是可以做到空間複雜度為 O(1)的,我們可以把複製的副節點插入到原連結串列中去,這樣也能把原節點與副節點進行關聯,進而
定位到隨機節點。例如,對於連結串列 1->2->3->null。首先生成副節點 1', 2', 3。然後把副節點插入到原節點的相鄰位置,即把原連結串列變成 1->1'->2->2'->3->3'->null。
這樣我們也可以在連線副節點的時候,找到相應的隨機節點。例如 1 的隨機節點是 3,則 1' 的隨機節點是 3'。顯然,1節點的隨機節點的下一個節點就是 1'的隨機節點。具體程式碼如下:
//方法二
public static Node1 copyListWithRand2(Node1 head){
Node1 cur = head;
Node1 next = null;
//把複製的節點插進去
while (cur != null) {
next = cur.next;
Node1 temp = new Node1(cur.value);//複製節點
temp.next = cur.next;
cur.next = temp;
cur = next;
}
//在一邊把複製的節點取出來一邊連線。
cur = head;
next = null;
while (cur != null) {
next = cur.next.next;//儲存原連結串列的下一個節點
cur.next.next = next != null ? next.next : null;
cur.next.rand = cur.rand != null ? cur.rand.next : null;
cur = next;
}
return head.next;
}
採用這種方法的時候,由於隨機節點有可能是空指標,隨意寫程式碼的時候要注意。
問題擴充
思考:如果是有兩個隨機指標呢?又該如何處理呢?三個呢?
【題目描述】
無
【要求】
無
【難度】
未知。
【解答】
提醒:別想太多了,保持清醒。
往期
【連結串列問題】打卡7:將單向連結串列按某值劃分成左邊小,中間相等,右邊大的形式
最後推廣下我的公眾號:苦逼的碼農,文章都會首發於我的公眾號,期待各路英雄的關注交流。