算法練習(9)-複雜帶隨機指針的單鏈表

所謂帶隨機指針的鏈表,結構如下:

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該指向誰,除非所有老節點全複製完)

 
有二種做法:
1、藉助額外的Map記錄“新-老”節點的映射
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個比較巧妙的思路

a、 先把每個節點複製一份, 掛在自己身後,相當於A -> B -> C 變成 A -> A' -> B -> B' -> C -> C'
b、 每2輪,處理random時,通過身後的“影子”,就能找到random的新節點在哪
c、 將鏈表分離, A -> A' -> B -> B' -> C -> C' 變成 A -> B -> C 和A' -> B' -> C' 返回A'
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;
    }

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章