所謂帶隨機指針的鏈表,結構如下:
class Node { int val; Node next; Node random; public Node(int val) { this.val = val; this.next = null; this.random = null; } }
除next外,還有一個隨機指針random,隨機指向鏈表中的某個元素(當然 :random也可能爲null). 複製的難度在於, 新節點剛new出來時,其random指向的另外1個“新”節點,可能還沒複製出來(即:首次無法確定新節點的random該指向誰,除非所有老節點全複製完)
public Node copyRandomList(Node head) { if (head==null){ return null; } Node h = head; Map<Node,Node> map = new HashMap<>(); Node newHead = new Node(head.val); Node curr = newHead; //第一輪,複製節點,random掛空,同時記錄處理過的老節點與新節點的映射關係 while(head!=null){ if (head.next!=null){ Node newNext = new Node(head.next.val); curr.next = newNext; } map.put(head,curr); head = head.next; curr = curr.next; } head = h; //第二輪,處理random指向,通過map映射,查到random指向的新節點 while(head!=null){ Node newNode = map.get(head); if (head.random!=null){ newNode.random = map.get(head.random); } head = head.next; } return newHead; }
2、如果要求空間複雜度爲O(1),還有1個比較巧妙的思路
public Node copyRandomList(Node head) { if (head==null){ return head; } Node curr = head; //複製自身,掛在身後 while(curr!=null){ Node newNode = new Node(curr.val); newNode.next = curr.next; curr.next = newNode; curr = curr.next.next; } //複製random curr = head; while(curr!=null){ if (curr.random!=null){ curr.next.random = curr.random.next; } curr = curr.next.next; } //分離鏈表 curr = head; Node newHead = head.next; while(curr!=null){ Node newCurr = curr.next; curr.next = curr.next.next; if (newCurr.next!=null){ newCurr.next = newCurr.next.next; } curr = curr.next; } return newHead; }