1. 程式人生 > >random指針的單鏈表深拷貝(LeetCode——Copy List with Random Pointer)

random指針的單鏈表深拷貝(LeetCode——Copy List with Random Pointer)

指針 tco nal alt The copy list next 代碼 solution

問題:

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.

結點的定義如下:

/**
* Definition for singly-linked list with a random pointer.
* class RandomListNode {
* int label;
* RandomListNode next, random;
* RandomListNode(int x) { this.label = x; }
* };
*/

分析:

原來的鏈表的結構如下圖所示:

技術分享圖片

註意一點,random的指針可以指向後面的結點,也可以指向前面的結點。

這裏提供兩種解法:

方法1:用hash表存儲結點信息,時間O(2n),空間O(n)

第一次遍歷原鏈表,並構建random為null的新鏈表,於此同時在hash表中存儲原結點和新結點的地址信息,原結點地址為key,新結點地址為value,即map<原結點地址,新結點地址>

第二次遍歷原鏈表,對於random不為空的結點,可以根據random的值,在hash表中找到random指向的節點對應的新結點的地址,再以此給新結點random賦值即可。

方法2:先改變原鏈表的結構,在恢復,時間O(2n),空間O(1)

這個方法需要3次遍歷,

第一次,構建新鏈表的結點,random為null,並且用原來鏈表節點的next指向對應的新結點,新結點的next指向原鏈表的下一個結點,如圖所示:

技術分享圖片

第二次,給新節點的random賦值,

p = head;
        while(p!=null){
            if(p.random != null){
                p.next.random = p.random.next;
            }
            p = p.next.next;
        }

第三次,恢復原鏈表和新鏈表的鏈表結構。

head2 = head.next;
        p = head;
        while(p!=null){
            p2 = p.next;
            p.next = p2.next;
            if (p2.next != null) p2.next = p2.next.next;
            p = p.next; 
        }

方法2的完整代碼:

public class Solution {
    public RandomListNode copyRandomList(RandomListNode head) {
        if(head == null)return null;
        RandomListNode head2,p2,p = head;
        while(p!=null){
            RandomListNode n = new RandomListNode(p.label);
            n.next = p.next;
            p.next = n;
            p = n.next;
        }
        p = head;
        while(p!=null){
            if(p.random != null){
                p.next.random = p.random.next;
            }
            p = p.next.next;
        }
        
        head2 = head.next;
        p = head;
        while(p!=null){
            p2 = p.next;
            p.next = p2.next;
            if (p2.next != null) p2.next = p2.next.next;
            p = p.next; 
        }
        return head2;
    }
}

random指針的單鏈表深拷貝(LeetCode——Copy List with Random Pointer)