链表 - 35.复杂链表的复制

在这里插入图片描述
在这里插入图片描述
思路1 :最简单的思路就是直接复制以next为一链的链表,在之后遍历原链表获取random的链表值,在复制链表上去从头到尾的寻找对应的random值。
举例:原链表的节点 A ,在复制链表上节点为 A’ ,A的random指向C,那么 A’ 节点的random也应该指向C‘,但是是A‘链表所在的C’,所以我们需要从头到尾的去寻找C’
这样时间复杂度就为O(n^2)

思路2:我们依旧直接复制原链表的next链,但是我们一边复制一遍存储,因为A节点对一个在复制链表中的节点是A’,所以我们用hashMap去存储,key为A,value为A’。那么我们想一下既然A的random为C,那么A‘对应的random为C’,所以我们就可以通过C直接定位到C‘。HashMap的查询速率几乎等于O(1)。
所以我们需要一个长为原链表长度 n 的的链表,也需要一个大小为 n 的hashMap来存储Key和Value。
所以使用了空间来换时间的思想
时间复杂度:O(n)
空间复杂度:O(n)

public static Node copyRandomList(Node head) {
        if(head == null) return null;
        HashMap<Node,Node> hashMap = new HashMap<>();
        //当random为null时,复制链表中的random也为null
        hashMap.put(null,null);
        Node copytemp = new Node(123);
        //先将原链表按next复制
        Node temp = head;
        Node copyhead = copytemp;
        while(temp != null){
            //边复制,边储存
            copytemp.next = new Node(temp.val);
            hashMap.put(temp,copytemp.next);
            temp = temp.next;
            copytemp = copytemp.next;
        }

        //再遍历原数组匹配random值
        temp = head;
        copytemp = copyhead.next;
        while(temp != null){
            copytemp.random = hashMap.get(temp.random);
            temp = temp.next;
            copytemp = copytemp.next;
        }
        return copyhead.next;

    }


思路三:我们复制的节点直接在原链表上增加复制的节点。
例如 A -》B -》C
复制节点后变成 A -> A’ -> B -> B’ -> C -> C’

那么原链表的A节点random为C节点。那么A的复制节点A’是A的next,那么A’的random也应该为C’,那么C‘的位置就在C节点的后面。所以我们就可以通过A找到C,再通过C找到C’,这样就找到了A‘的random。
所以我们再给节点复制random值时,我们就可以访问原链表节点,
A.next.random = A.random.next;

最后我们把原链表和复制链表分离。偶数为原链表,奇数位新链表。

    public static Node copyRandomList1(Node head) {
        if(head == null) return null;
        Node newHead = null;

        //把复制的节点直接连接到当前节点的后面
//        例如 A -》B -》C
//        复制节点后变成  A -> A' -> B -> B' -> C -> C'

        cloned(head);
        findRandom(head);
        return  getNewHead(head);


        //新链表提取出来
        //a a' b b' c c' null

    }

    //复制
    public static void cloned(Node head){
        Node temp = head;
        while(temp != null){
            Node copyNode = new Node(temp.val);
            copyNode.next = temp.next;
            temp.next = copyNode;
            temp = temp.next.next;
        }
    }
    public static void findRandom(Node head){
        //A.next.random = A.random.next;
        while(head != null ) {
            if(head.random != null){
                head.next.random = head.random.next;
            }
            head = head.next.next;
        }
    }
    public static  Node getNewHead(Node head){
        Node newHead = head.next;
        Node temp = null;
        while(head.next != null ){
            temp = head.next;
            head.next = head.next.next;
            head = temp;
        }
        return newHead;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值