1. 程式人生 > >leetcode 之 Copy List with Random Pointer

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;
    }
}