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

本文详细介绍了如何复制带有随机指针的链表,提供了两种不同的解决方案。方法一是通过原链表复制拆解,分别进行节点复制、构造random引用和拆解链表。方法二是利用HashMap存储新旧节点映射,再设置新节点的next和random引用。两种方法的时间复杂度均为O(n),但空间复杂度不同,第一种为O(1),第二种为O(n)。
摘要由CSDN通过智能技术生成

题目描述


方法1:原链表复制拆解


解题思路

  1. 一次遍历: 复制各节点
  2. 二次遍历:构造相同random引用
  3. 三次遍历:拆解成两个链表

代码

/*
// Definition for a Node.
class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}
*/
class Solution {
    public Node copyRandomList(Node head) {
        
        if(head == null) {
            return head;
        }

        Node cur = head;

        // 将各节点在其后复制一个
        while(cur != null) {
            // 注意new的时候 Node值为cur.val
            Node newNode = new Node(cur.val);
            newNode.next = cur.next;
            cur.next = newNode;
            cur = newNode.next;
        }

        cur = head;

        while(cur != null) {
            // 如果rodom不为空,代表为原链表节点
            if (cur.random != null){
                /*左边 cur.next.random:新链表节点的random ,
                **右边  cur.random.next:原链表节点的random的下个节点,该节点值和原链表节点的random引用值相同,但是属于新构造的链表
                *注意不能使新链表的random指向原链表节点
                */ 
                cur.next.random = cur.random.next;
            }
            cur = cur.next.next;
        }


        // 拆解链表,注意原链表要还原
        cur = head.next;
        Node prev = head;
        Node copyNode = head.next;


        //注意循环中有用到cur.next.next, 则终止条件为cur.next = null
        while(cur.next != null) {
            // 改变next指针指向
            prev.next = prev.next.next;
            cur.next = cur.next.next;
            // 迭代遍历
            prev = prev.next;
            cur = cur.next;
        }

        // 循环终止时,cur.next已为null, 而prev.next还不是
        prev.next = null;
        return copyNode;
    }
}


复杂度分析

时间复杂度:O(n)。三次遍历。
空间复杂度:O(1)。在原链表上进行操作。


方法2 HashMap


解题思路

  1. 循环遍历链表,储存新旧节点键值对。key 旧节点, value 新节点;
  2. 循环遍历链表,使新节点next引用指向旧节点的next;使新节点random引用指向旧节点的random;

代码实现

class Solution {
    public Node copyRandomList(Node head) {
        
        if(head == null) {
            return head;
        }

        Node cur = head;
        Map<Node, Node> map = new HashMap<>();

        while(cur != null) {
            map.put(cur, new Node(cur.val));
            cur = cur.next;
        }

        cur = head;

        while(cur != null) {
            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)。两次遍历。
空间复杂度:O(n)。Hashmap储存了同样大小的键值对。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值