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

本文介绍了如何复制一个包含random指针的复杂链表。提供了两种解题方法,一种是使用哈希表记录节点对应关系,另一种是通过拼接和拆分链表。在哈希表方法中,通过遍历链表创建新节点并建立映射,然后遍历映射设置新节点的next和random指针。在拼接+拆分链表的方法中,先复制节点并将新节点插入到原节点之后,再填充random指针,最后拆分链表得到复制的链表。
摘要由CSDN通过智能技术生成

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

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

示例 1:

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

示例 2:

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]

示例 3:

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]

示例 4:

输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。

提示:

-10000 <= Node.val <= 10000
Node.random 为空(null)或指向链表中的节点。
节点数目不超过 1000 。

解题思路

该题具有两种解题思路 解题的核心是 记录好 旧节点与新节点之间的对应关系

  1. 使用 哈希表映射 来存储 Node

    对于源链表中的每一个节点node和其复制节点newNode,都有唯一键值对<node,newNode>

    对于newNode , newNode.next = map.get(node.next);

     					 newNode.random = map.get(current.random); 
    
  2. 拼接 + 拆分 链表来记录Node

    源链表 node1 -> node2 -> node3 -> node4 …

    新链表 newNode1 -> newNode2 -> newNode3 -> newNode4 …

    拼接为链表:

    node1 -> newNode1 -> node2 -> newNode2 …

    通过以上链表可以解决random指针问题

    newNode.random = node1.random.next;

    拆分该链表:

    node.next = node.next.next;

    newNode = newNode.next.next;

代码示例

  1. Map方法
/*
// 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>{
        Map<Node,Node> map = new HashMap<Node,Node>();
        Node current = head;
        while(current!=null){
            Node node = new Node(current.val);
            map.put(current,node);
            current = current.next;
        }
        current = head;
        while(current!=null)
        {
            Node newNode = map.get(current);
            newNode.next = map.get(current.next);
            newNode.next = map.get(current.random);
            current = current.next;
        }
        return map.get(head);
    }
}

在这里插入图片描述

2.拼接 + 拆分 链表

public Node copyRandomList(Node head){
    if(head==null)
    {
        return head;
    }
    //复制每一个节点,并将新节点放在旧节点的后面
    /*
    newcurrent.next = current.next;
    current.next = newcurrent;
    */
    Node newHead = new Node(0);
    Node current = head;
    Node newcurrent = headHead;
    while(current!=null)
    {
        newcurrent = new Node(current.val);
        newcurrent.next = current.next;
        current.next = newcurrent;
        current = current.next.next;
    }
    //在上面已经形成了一个以head为头的复制组合链表
    // a -> a' -> b -> b' ....
    //接下来 把每一个新节点的 random指针补全
    current = head;
    while(current!=null)
    {
        if(current.random == null)
        {
            current.next.random = null;
        }else{
            current.next.random = current.random.next;
        }
        current = current.next;
    }
    //接下来把原链表和新链表拆开
    current = head;
    newHead = current.next;
    newcurrent = newHead;
    while(current!=null)
    {
        if(newcurrent.next==null){
            current.next = null;
            break;
        }
        current.next = current.next.next;
        newcurrent.next = newcurrent.next.next;
        current = current.next;
        newcurrent = newcurrent.next;
    }
    return newHead;
}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值