【Leetcode C++】2_7. [code] 複製帶隨機指針的鏈表

7. [code] 複製帶隨機指針的鏈表

7.1 題目

Leetcode 138

給定一個鏈表,每個節點包含一個額外增加的隨機指針,該指針可以指向鏈表中的任何節點或空節點。

要求返回這個鏈表的深拷貝。

示例:
Alt

輸入:
{“KaTeX parse error: Expected '}', got 'EOF' at end of input: …":"1","next":{"id”:“2”,“next”:null,“random”:{“KaTeX parse error: Expected 'EOF', got '}' at position 9: ref":"2"}̲,"val":2},"rand…ref”:“2”},“val”:1}

解釋:
節點 1 的值是 1,它的下一個指針和隨機指針都指向節點 2 。
節點 2 的值是 2,它的下一個指針指向 null,隨機指針指向它自己。

提示:

你必須返回給定頭的拷貝作爲對克隆列表的引用。

難度:中等

7.2. 思路

假定上述的帶隨機指針的鏈表的類型稱爲Node類。

定義如下,包含值val,指向下一節點的指針next,和隨機指針random.

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;

    Node() {}

    Node(int _val, Node* _next, Node* _random) {
        val = _val;
        next = _next;
        random = _random;
    }
};
*/

需要2個map,一個儲存原Node鏈表的每個節點的地址和序號,另一個存儲新Node鏈表的每個節點的地址和序號;由於新Node鏈表是原鏈表的拷貝,這裏的序號的相同的,因此,第二的map可以用vector代替。

先創建一個新Node鏈表,則可以將這一新鏈表的每個節點的地址push入上述的vector,即這一vector儲存了新Node鏈表的每個節點地址;

再遍歷原Node鏈表,將原Node鏈表的每個節點的地址和序號分別儲存入map的KEY和VALUE;

對新的Node鏈表需要兩個操作:

  1. 每個節點next指針相連;
  2. 每個節點,如果存在ranndom,則random的指向;

7.3. 代碼

class Solution {
public:
    Node* copyRandomList(Node* head) {
        if (!head) return NULL;
        //定義<Node*, int>類型的map和<Node*>類型的vector
        std::map<Node*, int> node_map;
        std::vector<Node*> node_vec;
        //新鏈表的每個節點的地址push入上述的vector
        Node* ptr = head;
        int i=0;
        while(ptr){
            //vector存入新Node鏈表的地址
            node_vec.push_back(new Node(ptr->val)); 
            //map存入原Node鏈表的地址和序號
            node_map[ptr]=i;
            //下一個節點
            ptr = ptr->next;
            i++;
        }
        //將0加入node_vec的最末,確保後續node_vec最後一個節點的next指針指向不出錯
        node_vec.push_back(0);
        //遍歷原Node鏈表,
        ptr = head;
        i=0;
        while(ptr){
            //每個節點next指針相連
            node_vec[i]->next = node_vec[i+1];
            //每個節點,如果存在ranndom,則random的指向
            if (ptr->random){
                int id = node_map[ptr->random]; //該節點random指向的節點的序號
                node_vec[i]->random = node_vec[id];
            }
            ptr = ptr->next;
            i++;
        }
        return node_vec[0];
    }
};

提交到oj上有錯誤

下面這個方法簡直神仙方法,太棒了:
先寫一下代碼

class Solution{
public:
    Node* copyRandomList(Node* head){
        if (!head) return nullptr;
        /* 將拷貝的節點接在原節點後面,再繼續接下一個原節點 */
        for (Node* cur = head; cur != nullptr; ){
            Node* node = new Node(cur->val);
            node->next = cur->next;
            cur->next = node;
            cur = node->next;
        }
        /* 確定每個新節點的random指向 */
        for (Node* cur = head; cur != nullptr;) {
            if (cur->random != NULL){
                cur->next->random = cur->random->next;
            }
            else{
                cur->next->random = NULL;
            }
            cur = cur->next->next;  
        }

        /* 分離兩個鏈表 */
        Node dummy(-1);
        Node* new_node = &dummy;
        for (Node* cur = head; cur != nullptr; ){
            new_node->next = cur->next;
            if(cur->next != NULL){
                cur->next = cur->next->next;
            }
            else{
                cur->next = NULL;
            }
            new_node = new_node->next;
            cur = cur->next;
        }

        return dummy.next;
    }
    
};
class Solution { 
public:
RandomListNode *copyRandomList(RandomListNode *head) { 
    for (RandomListNode* cur = head; cur != nullptr; ) { 
        RandomListNode* node = new RandomListNode(cur->label); 
        node->next = cur->next; 
        cur->next = node; 
        cur = node->next;
    }
    for (RandomListNode* cur = head; cur != nullptr; ) { 
        if (cur->random != NULL) 
            cur->next->random = cur->random->next;
        cur = cur->next->next; 
    }

    RandomListNode dummy(-1); 
    for (RandomListNode* cur = head, *new_cur = &dummy; cur != nullptr; ) {
        new_cur->next = cur->next; 
        new_cur = new_cur->next; 
        cur->next = cur->next->next; 
        cur = cur->next;
    } 
    return dummy.next; 
    } 
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章