算法练习(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;
    }

  

作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/yjmyzz/p/15448823.html