leetcode 之 Copy List with Random Pointer
題目如下:
A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
題目大意:深拷貝一個連結串列,連結串列除了含有next指標外,還包含一個random指標,該指標指向字串中的某個節點或者為空。
節點定義為:
struct RandomListNode {
int label;
RandomListNode *next, *random;
RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
};
假設原始連結串列如下,細線表示next指標,粗線表示random指標,沒有畫出的指標均指向NULL:
演算法1:我們在構建新連結串列的節點時,儲存原始連結串列的next指標對映關係,並把指標做如下變化(藍色為原始連結串列節點,紫紅色為新連結串列節點):
然後在上圖的基礎上進行如下兩步
1、構建新連結串列的random指標:比如new1->random = new1->random->random->next, new2->random = NULL, new3-random = NULL, new4->random = new4->random->random->next
2、恢復原始連結串列:根據最開始儲存的原始連結串列next指標對映關係恢復原始連結串列
該演算法時間空間複雜度均為O(N)
演算法2:該演算法更為巧妙,不用儲存原始連結串列的對映關係,構建新節點時,指標做如下變化,即把新節點插入到相應的舊節點後面:
同理分兩步
1、構建新節點random指標:new1->random = old1->random->next, new2-random = NULL, new3-random = NULL, new4->random = old4->random->next
2、恢復原始連結串列以及構建新連結串列:例如old1->next = old1->next->next, new1->next = new1->next->next
該演算法時間複雜度O(N),空間複雜度O(1)
下面給出第二種演算法的實現:
/**
* 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) {
return recover(random(copy(head)));
}
private RandomListNode copy(RandomListNode head){
RandomListNode p = head;
while(p != null){
RandomListNode q = new RandomListNode(p.label);
q.random = null;
RandomListNode temp = p;
p = p.next;
q.next = p;
temp.next = q;
}
return head;
}
private RandomListNode random(RandomListNode head){
RandomListNode oldnode = head;
if(head == null) return null;
RandomListNode newnode = head.next;
while(oldnode != null){
if(oldnode.random != null)
newnode.random = oldnode.random.next;
oldnode = newnode.next;
if(oldnode != null)
newnode = oldnode.next;
}
return head;
}
private RandomListNode recover(RandomListNode head){
RandomListNode oldnode = head;
if(head == null) return null;
RandomListNode newHead = head.next;
RandomListNode newnode = newHead;
while(oldnode != null){
oldnode.next = newnode.next;
oldnode = newnode.next;
if(oldnode != null){
newnode.next = oldnode.next;
newnode = oldnode.next;
}
}
return newHead;
}
}