LeetCode 複製帶隨機指標的連結串列

hestyle發表於2019-02-23

給定一個連結串列,每個節點包含一個額外增加的隨機指標,該指標可以指向連結串列中的任何節點或空節點。
要求返回這個連結串列的深拷貝。
示例:
在這裡插入圖片描述

輸入:
{"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}
解釋:
節點 1 的值是 1,它的下一個指標和隨機指標都指向節點 2 。
節點 2 的值是 2,它的下一個指標指向 null,隨機指標指向它自己。

提示:
你必須返回給定頭的拷貝作為對克隆列表的引用。
思路分析:利用map關聯式容器輔助。第一遍掃描複製節點,並將原連結串列中的所有節點與新複製的節點一一對應的關聯,再掃描一遍原連結串列複製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;
    }
};
*/
class Solution {
public:
	Node* copyRandomList(Node* head) {
		map<Node*, Node*> myMap;
		Node *pHead = head, *tempPtr;
		//掃描連結串列,複製所有的節點
		while (pHead != NULL) {
			tempPtr = new Node(pHead->val, pHead->next, pHead->random);
			myMap[pHead] = tempPtr;//將原節點與新節點一一對應的關聯
			pHead = pHead->next;
		}
		myMap[NULL] = NULL;
		pHead = head;
		//再次掃描連結串列,複製next、random指標
		while (pHead != NULL){
			myMap[pHead]->next = myMap[pHead->next];
			myMap[pHead]->random = myMap[pHead->random];
            pHead = pHead->next;
		}
		return myMap[head];
	}
};

在這裡插入圖片描述
方法二:

① 首先掃描連結串列,複製所有的節點,並將複製的節點插入到原先節點的後面。
②再次掃描節點,複製所有原節點random指標域、
③再將兩個連結串列拆開
演算法示意圖
初始狀態
在這裡插入圖片描述
執行第一步複製節點
在這裡插入圖片描述
執行第二步複製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;
    }
};
*/
class Solution {
public:
	Node* copyRandomList(Node* head) {
        if (head == NULL){
            return NULL;
        }
		Node *pHead = head, *tempPtr;
		//掃描連結串列,複製所有的節點
		while (pHead != NULL) {
			tempPtr = new Node(pHead->val, pHead->next, pHead->random);//複製節點
			//將這個複製的節點插入到複製源的後面
			tempPtr->next = pHead->next;
			pHead->next = tempPtr;
			pHead = pHead->next->next;//移動必須是移動兩個一次,因為剛剛在後面插入了一個複製的節點
		}
		//再次掃描節點,複製random節點
		pHead = head;
		while (pHead != NULL) {
			if (pHead->random != NULL) {
				//pHead->next是pHead的複製,所以pHead->random->next的複製是pHead->random
				pHead->next->random = pHead->random->next;
			}
			else {
				pHead->next->random = NULL;
			}
			pHead = pHead->next->next;
		}
		//在將兩個連結串列拆開
		pHead = head;
		Node *copyHead = pHead->next;
		while (pHead != NULL) {
			tempPtr = pHead->next;
			pHead->next = pHead->next->next;
			if (tempPtr->next != NULL) {
				tempPtr->next = tempPtr->next->next;
			}
            pHead = pHead->next;
		}
		return copyHead;
	}
};

在這裡插入圖片描述

相關文章