【链表】复杂链表的复制

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

复杂链表的定义
在这里插入图片描述


哈希表解法

由于复杂链表的节点label是唯一的,因此可以使用哈希表, 将label作为键值,node作为value,每次添加next或者random节点时先判断哈希表中是否已存在该label对应的节点,若存在,则返回该节点,若不存在则新建一个节点并添加到哈希表中。这种解法相当于用空间换时间,只需遍历一次链表即可

import java.util.HashMap;

public class Solution {
    public RandomListNode Clone(RandomListNode pHead) {
        if (pHead == null)
            return null;
        RandomListNode head, tail;
        HashMap<Integer, RandomListNode> hashMap = new HashMap<>();

        int label = pHead.label;
        RandomListNode next, random;
        head = new RandomListNode(label);
        tail = head;
        hashMap.put(label, tail);
        while (pHead != null) {
            next = pHead.next;
            random = pHead.random;
            RandomListNode tmp;
            if (next != null) {
                if (hashMap.containsKey(next.label))
                    tmp = hashMap.get(next.label);
                else {
                    tmp = new RandomListNode(next.label);
                    hashMap.put(next.label, tmp);
                }
            } else {
                tmp = null;
            }
            tail.next = tmp;

            if (random != null) {
                if (hashMap.containsKey(random.label))
                    tmp = hashMap.get(random.label);
                else {
                    tmp = new RandomListNode(random.label);
                    hashMap.put(random.label, tmp);
                }
            } else {
                tmp = null;
            }
            tail.random = tmp;

            tail = tail.next;
            pHead = pHead.next;
        }
        return head;
    }
}

三步法

  1. 先在原链表的基础上复制链表,即在每个节点后插入克隆的节点,例如:
    1-2-3-4-5插入克隆节点后变成1-1-2-2-3-3-4-4-5-5
  2. 这一步根据原链表的random设置克隆链表的random指向
  3. 最后将两个链表拆分,即设置两个链表的next指向
public static RandomListNode Clone(RandomListNode pHead) {
       if (pHead == null)
           return null;
       RandomListNode now = pHead;
       // 在每个节点后插入克隆节点
       while (now != null) {
           RandomListNode cloneNode, tmpNext;
           cloneNode = new RandomListNode(now.label);
           tmpNext = now.next;
           now.next = cloneNode;
           cloneNode.next = tmpNext;
           now = now.next.next;
       }
       
       // 设置random节点
       now = pHead;
       while (now != null) {
           now.next.random = now.random == null ? null : now.random.next;
           now = now.next.next;
       }

       // 拆分链表
       RandomListNode head = pHead.next;
       now = pHead;
       while (now != null) {
           RandomListNode tmpNext = now.next;
           now.next = tmpNext.next;
           tmpNext.next = tmpNext.next == null ? null : tmpNext.next.next;
           now = now.next;
       }
       return head;
   }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值