5. 复杂链表的复制(剑指 Offer 35)

题目描述

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

1)节点的引用保存的只是地址值,需要重写toString方法才能将引用的具体内容进行输出;

2)链表问题:操作的仍然只是单独的一个节点;只是节点中含有节点类型的变量,可以存储地址寻找下一个节点,逻辑上成为了一个不连续的链;

考察深拷贝的知识点。

答案中用到的Map:哈希表的特点,一一映射的关系,用Key找到Value(准确找到),先一一对应的创建出节点,再用Key取到新创建的节点进行连接。

map.get(key)得到value值

哈希表中放对象,对象作为Key值来进行Value的寻找。

自己能想到的方式

1.创建一个新的链表,逐项将head中的内容连接到新的链表上,错误可以当作正常链表的复制

答案解析说到,不能直接创建新链表复制,是因为会出现 随机节点还未创建的情况!「当前节点的随机指针指向的节点」可能还没创建

还是不太能理解

重点是先将节点都创建出来,再进行引用指向,此时就不会出现找不到随机random节点的情况。

class Solution {

    public Node copyRandomList(Node head) {
       
        Node newNode = new Node(0);//和head不同位置
        Node cur = newNode;//记录了相同的地址值,可以通过该地址值找到新的链表
        while(head != null){

            Node next = head.next;//拿到下一个节点

            //复制操作
            cur.val = head.val;
            cur.next = head.next;
            cur.random = head.random;
            
            head = next;
            cur = cur.next;
        }
        return newNode;
    }
}

答案代码:问题的关键就是 不管random,先将所有的节点构建出来,再进行连接。

1.哈希表: 

class Solution {

    public Node copyRandomList(Node head) {
       
        if(head == null) return null;
        Map<Node,Node> map = new HashMap<Node,Node>();
        Node cur = head;
        
        //创建哈希表,将需要连接的节点先创建出来,此时引用未指向,说明next和random都是null
        while(cur != null){
            map.put(cur,new Node(cur.val));
            cur = cur.next;
        }

        //进行引用关系的连接
        cur = head;
        while(cur != null){
            //map.get(cur).next = cur.next; 应该指向新创建的节点
            //map.get(cur).random = cur.random;
            map.get(cur).next = map.get(cur.next);
            map.get(cur).random = map.get(cur.random);
            cur = cur.next;
        }
        return map.get(head);
    }
}
作者:jyd
链接:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/solution/jian-zhi-offer-35-fu-za-lian-biao-de-fu-zhi-ha-xi-/
来源:力扣(LeetCode)

哈希+回溯

class Solution {
    Map<Node, Node> cachedNode = new HashMap<Node, Node>();

    public Node copyRandomList(Node head) {
        if (head == null) {
            return null;
        }
        if (!cachedNode.containsKey(head)) {
            //没有该节点,就先创建
            Node headNew = new Node(head.val);
            cachedNode.put(head, headNew);

            //进行引用的指向,回溯;
            //回溯为了避免random还未创建,如果哈希表中有直接返回,如果没有就创建
            headNew.next = copyRandomList(head.next);
            headNew.random = copyRandomList(head.random);
        }
        return cachedNode.get(head);
    }
}

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/solution/fu-za-lian-biao-de-fu-zhi-by-leetcode-so-9ik5/
来源:力扣(LeetCode)

2. 拆分+拼接

class Solution {
    public Node copyRandomList(Node head) {
        if(head == null) return null;
        Node cur = head;
        // 1. 复制各节点,并构建拼接链表
        while(cur != null) {
            Node tmp = new Node(cur.val);
            tmp.next = cur.next;
            cur.next = tmp;
            cur = tmp.next;
        }
        // 2. 构建各新节点的 random 指向
        cur = head;
        while(cur != null) {
            if(cur.random != null)
                cur.next.random = cur.random.next;
            cur = cur.next.next;
        }
        // 3. 拆分两链表
        cur = head.next;
        Node pre = head, res = head.next;
        while(cur.next != null) {
            pre.next = pre.next.next;
            cur.next = cur.next.next;
            pre = pre.next;
            cur = cur.next;
        }
        pre.next = null; // 单独处理原链表尾节点
        return res;      // 返回新链表头节点
    }
}

作者:jyd
链接:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/solution/jian-zhi-offer-35-fu-za-lian-biao-de-fu-zhi-ha-xi-/
来源:力扣(LeetCode)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值