1. 程式人生 > >138 複雜連結串列的深度拷貝 copy list with random pointer

138 複雜連結串列的深度拷貝 copy list with random pointer

問題分析:

一個複雜的連結串列,節點中有一個指向本連結串列任意某個節點的隨機指標(也可能為空),求這個連結串列的深度拷貝

思路:

此題有兩種方法,一種是按照原連結串列next的順序依次建立節點,並處理好新連結串列的next指標,同時把原節點與新節點的對應關係儲存到一個hash_map中,然後第二次迴圈將random指標處理好。這種方法的時間複雜度是O(n),空間複雜度也是O(n)。

第二種方法則是在原連結串列的每個節點之後插入一個新的節點,這樣原節點與新節點的對應關係就已經明確了,因此不需要用hash_map儲存,但是需要第三次迴圈將整個連結串列拆分成兩個。這種方法的時間複雜度是O(n),空間複雜度是O(1)。

但是利用hash_map的方法具有其他的優點,如果在迴圈中加入一個判斷,就可以檢測出連結串列中是否有迴圈;而第二種方法則不行,會陷入死迴圈。

/**
 * Definition for singly-linked list with a random pointer.
 * class RandomListNode {
 *     int label;
 *     RandomListNode next, random;
 *     RandomListNode(int x) { this.label = x; }
 * };
 */
public class Solution {
    public RandomListNode copyRandomList(RandomListNode head) {
        HashMap<RandomListNode,RandomListNode> map=new HashMap<>();
        RandomListNode cur=head;
        //第一步,將結點存入雜湊表
        while(cur!=null){
            RandomListNode newNode=new RandomListNode(cur.label);
            map.put(cur,newNode);
            cur=cur.next;
        }
        //
        cur=head;
        while(cur!=null){
            RandomListNode node=map.get(cur);
            node.next=map.get(cur.next);
            node.random=map.get(cur.random);
            cur=cur.next;
        }
        return map.get(head);
    }
}

方法二:c++

/**
 * Definition for singly-linked list with a random pointer.
 * struct RandomListNode {
 *     int label;
 *     RandomListNode *next, *random;
 *     RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        if(head==NULL){
            return NULL;
        }

        RandomListNode *now = head;         //複製各個節點
        while(now){
            RandomListNode *copy = new RandomListNode(now->label);
            copy->next = now->next;
            now->next = copy;
            now = copy->next;
        }

        for(now=head; now; now=now->next->next){        //複製random指標域
            now->next->random = (now->random)?now->random->next:NULL;
        }

        RandomListNode* h = head->next;     //斷開成兩個連結串列
        RandomListNode* t = h;
        RandomListNode* tail = head;
        for(;;){
            tail->next = t->next;
            tail = tail->next;
            if(tail==NULL){
                break;
            }
            t->next = tail->next;
            t = t->next;
        }
        return h;
    }
};