[剑指 Offer] 35. 复杂链表的复制

题目

leetcode 剑指 Offer 35. 复杂链表的复制

在这里插入图片描述
在这里插入图片描述

提供的Node:

static class Node {
    
    
    int val;
    Node next;
    Node random;

    public Node(int val) {
    
    
        this.val = val;
        this.next = null;
        this.random = null;
    }
}

题解

解法一:用hashMap很简单,key为原节点,value为副本节点,然后根据key的next和random,让value来拼成副本链表。

    /**
     * 使用哈希表,key是原链表的节点,value是copy的节点
     * 然后一一拼接
     * 最后返回的是map中key为head的值,它就是新链表的头节点
     * @param head
     * @return
     */
    public static Node copyRandomList(Node head) {
    
    
        if(head == null) {
    
    
            return null;
        }
        Node cur = head;

        // key是原链表的节点,value是copy的节点
        HashMap<Node, Node> map = new HashMap<>();
        while(cur != null) {
    
    
            map.put(cur, new Node(cur.val));
            // 移动
            cur = cur.next;
        }
        // 拼接
        cur = head;
        while(cur != null) {
    
    
            // 直接在map拼,map.get(cur)就是新链表的节点
            map.get(cur).next = map.get(cur.next);
            map.get(cur).random = map.get(cur.random);
            cur = cur.next;
        }

        return map.get(head);
    }

复杂度:

  • 时间复杂度:O(N)
  • 空间复杂度:一共存储N个节点,所以O(N)。

解法二:在原链表中的每个原节点的next添加它的副本节点,它的副本节点的next指向原先原节点的next。然后搞好副本节点的random,很简单,就是指向原节点的random的next。最后再把副本节点从原链表分离,拼成副本链表。不懂就看图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码:

   /**
     * 不用哈希表
     * @param head
     * @return
     */
    public static Node copyRandomList(Node head) {
    
    
        if(head == null) {
    
    
            return null;
        }
        Node cur = head;
        Node next = null;
        Node copyNode = null;
        // 先把克隆节点放在每一个旧节点后面
        // 1->2
        // 1->1'->2
        while(cur != null) {
    
    
            // 暂存
            next = cur.next;
            // 插入克隆节点
            cur.next = new Node(cur.val);
            // 接回去
            cur.next.next = next;
            // 移到下一个旧节点
            cur = next;
        }
        // 先搞好random,有了上面的结构,让克隆节点指向克隆random很简单
        // 旧节点的random的下一个节点,就是旧节点的克隆节点指向的random
        cur = head;
        while(cur != null) {
    
    
            // 旧节点和克隆节点一对一对的处理
            next = cur.next.next;

            copyNode = cur.next;

            copyNode.random = cur.random != null ? cur.random.next : null;

            // 移动2个节点
            cur = next;
        }
        // 把克隆节点从旧链表分离
        // 克隆链表的头节点
        Node copyNodeHead = head.next;
        cur = head;
        while(cur != null) {
    
    
            next = cur.next.next;
            copyNode = cur.next;
            cur.next = next; // 旧节点接回旧节点
            copyNode.next = next != null ? next.next : null; // 克隆节点接上克隆节点
            cur = cur.next;
        }
        return copyNodeHead;
    }

复杂度:

  • 时间复杂度:O(N)
  • 空间复杂度:如果不计算开辟副本节点带来的空间开销,那么就是O(1)

猜你喜欢

转载自blog.csdn.net/weixin_41800884/article/details/107992474
今日推荐