剑指offer编程题解法汇总25-复杂链表的复制

题目:复杂链表的复制

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

 

解题思路:这题一开始想很简单啊。后来开始实现的时候才发现难点所在,难点就是遍历复制的时候由于存在random节点,而random节点是随机位置的,所以复制某个节点的时候很可能存在random还未生成的场景。

为了解决这个问题,我有两个思路:

1:遍历第一遍链表节点,用一个List1进行保存,并使用HashMap记录每个节点的在List中的位置。同时用另外一个List2记录复制的节点。复制的节点只复制,不对next,random赋值。然后对List1进行遍历,同时取List2中相同位置的节点进行链表的生成,并利用HashMap对List2中的节点random进行赋值即可。下面的代码即是对第一种思路的实现。

package com.solution;


import com.solution.model.RandomListNode;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * 复杂链表的复制
 */
public class Solution {

    public static void main(String[] args) {
        Solution solution = new Solution();

        RandomListNode node1 = new RandomListNode(1);
        RandomListNode node2 = new RandomListNode(2);
        RandomListNode node3 = new RandomListNode(3);
        RandomListNode node4 = new RandomListNode(4);
        RandomListNode node5 = new RandomListNode(5);
        RandomListNode node6 = new RandomListNode(6);
        RandomListNode node7 = new RandomListNode(7);

        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node6;
        node6.next = node7;

        node1.random = node3;
        node2.random = node4;
        node3.random = node5;
        node4.random = node6;
        node5.random = node7;
        node6.random = node1;
        node7.random = node2;

        RandomListNode clone = solution.Clone(node1);
        System.out.println(clone);

    }

    HashMap<RandomListNode, Integer> oldNodeMap = new HashMap<>();
    ArrayList<RandomListNode> oldNodeList = new ArrayList<>();
    ArrayList<RandomListNode> newNodeList = new ArrayList<>();//存储新创建的节点

    public RandomListNode Clone(RandomListNode pHead) {
        if (pHead == null) {
            return null;
        }

        //第一遍遍历构建数据集合,
        do {
            oldNodeList.add(pHead);
            newNodeList.add(cloneNode(pHead));
            oldNodeMap.put(pHead, oldNodeList.indexOf(pHead));
            pHead = pHead.next;
        } while (pHead != null);
        //第二遍编辑数据集合返回最终值
        RandomListNode nextHead = null;
        RandomListNode currentNode = null;
        for (int i = 0; i < oldNodeList.size(); i++) {
            RandomListNode oldNode = oldNodeList.get(i);
            RandomListNode newNode = newNodeList.get(i);
            if (i == 0) {
                nextHead = newNode;
            }
            if (currentNode != null) {
                currentNode.next = newNode;
            }
            if (oldNode.random != null) {
                Integer index = oldNodeMap.get(oldNode.random);
                newNode.random = newNodeList.get(index);
            }
            currentNode = newNode;
        }
        return nextHead;
    }


    public RandomListNode cloneNode(RandomListNode pHead) {
        RandomListNode node = new RandomListNode(pHead.label);
        return node;
    }
}

 

2:遍历复杂链表,同时进行新链表节点的生成。生成新的链表节点的next暂不赋值,生成节点的random节点进行赋值(如果该节点Map中存在就复用,不存在就创建)

所以HashMap当中缓存,Key=老的节点对象 Value=新的节点对象。

package com.solution;


import com.solution.model.RandomListNode;

import java.util.HashMap;

/**
 * 复杂链表的复制
 */
public class Solution {

    public static void main(String[] args) {
        Solution solution = new Solution();

        RandomListNode node1 = new RandomListNode(1);
        RandomListNode node2 = new RandomListNode(2);
        RandomListNode node3 = new RandomListNode(3);
        RandomListNode node4 = new RandomListNode(4);
        RandomListNode node5 = new RandomListNode(5);
        RandomListNode node6 = new RandomListNode(6);
        RandomListNode node7 = new RandomListNode(7);

        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node6;
        node6.next = node7;

        node1.random = node3;
        node2.random = node4;
        node4.random = node6;
        node5.random = node7;
        node6.random = node1;
        node7.random = node2;

        RandomListNode clone = solution.Clone(node1);
        System.out.println(clone);

    }

    HashMap<RandomListNode, RandomListNode> nodeMap = new HashMap<>();

    public RandomListNode Clone(RandomListNode pHead) {
        if (pHead == null) {
            return null;
        }
        RandomListNode nextHead = null;
        RandomListNode currentNode = null;
        while (pHead != null) {
            RandomListNode node = cloneNode(pHead);
            node.random = cloneNode(pHead.random);
            if (nextHead == null) {
                nextHead = node;
                currentNode = node;
            } else {
                currentNode.next = node;
                currentNode = node;
            }
            pHead = pHead.next;
        }
        return nextHead;
    }


    public RandomListNode cloneNode(RandomListNode pHead) {
        if (pHead == null) {
            return null;
        }
        RandomListNode node = nodeMap.get(pHead);
        if (node == null) {
            node = new RandomListNode(pHead.label);
            nodeMap.put(pHead, node);
        }
        return node;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失落夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值