【剑指offer】JZ35 复杂链表的复制

文章介绍了如何对包含random指针的复杂链表进行深拷贝,方法包括组合链表、双指针遍历和使用哈希表建立映射。主要步骤包括创建拷贝节点、连接next指针、处理random指针以及最后拆分链表为两个独立部分。
摘要由CSDN通过智能技术生成

1 问题

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)。 下图是一个含有5个结点的复杂链表。图中实线箭头表示next指针,虚线箭头表示random指针。为简单起见,指向null的指针没有画出。

在这里插入图片描述

示例:
输入:{1,2,3,4,5,3,5,#,2,#}
输出:{1,2,3,4,5,3,5,#,2,#}
解析:我们将链表分为两段,前半部分{1,2,3,4,5}为ListNode,后半部分{3,5,#,2,#}是随机指针域表示。
以上示例前半部分可以表示链表为的ListNode:1->2->3->4->5
后半部分,3,5,#,2,#分别的表示为
1的位置指向3,2的位置指向5,3的位置指向null,4的位置指向2,5的位置指向null
如下图:

在这里插入图片描述
示例1
输入:{1,2,3,4,5,3,5,#,2,#}
返回值:{1,2,3,4,5,3,5,#,2,#}

2 答案

这题直接不会

官方解

  1. 组合链表,双指针

正常链表的复制,从头到尾遍历链表,对于每个节点创建新的节点,赋值,并将其连接好就可以了。这道题的不同之处在于我们还要将随机指针连接好,我们创建节点的时候,有可能这个节点创建了,但是它的随机指针指向的节点没有创建,因此创建的时候只能连接指向后面的指针,无法连接随机指针。

等链表连接好了,再连接随机指针的话,我们又难以找到这个指针指向的位置,因为链表不支持随机访问。但是吧,我们待拷贝的链表可以通过随机指针访问节点,那么我们不如将拷贝后的每个节点插入到原始链表相应节点之后,这样连接random指针的时候,原始链表random指针后一个元素就是原始链表要找的随机节点,而该节点后一个就是它拷贝出来的新节点,这不就可以连上了嘛。

这样等随机指针链表完成之后,再遍历链表,将其拆分按照奇偶序列拆分成两个链表:只需要每次越过相邻节点连接就可以了。

  • step 1:遍历链表,对每个节点新建一个拷贝节点,并插入到该节点之后。
  • step 2:使用双指针再次遍历链表,两个指针每次都移动两步,一个指针遍历原始节点,一个指针遍历拷贝节点,拷贝节点的随机指针跟随原始节点,指向原始节点随机指针的下一位。
  • step 3:再次使用双指针遍历链表,每次越过后一位相连,即拆分成两个链表。
class Solution:
    def Clone(self, pHead):
        if pHead is None:
            return pHead
        cur = pHead
        while cur is not None:
            clone = RandomListNode(cur.label)
            clone.next = cur.next
            cur.next = clone
            cur = clone.next
        cur = pHead
        clone = pHead.next
        res = pHead.next  # 这里res是pHead.next,即新链表的头节点,后面这个节点会和原链表的节点打断
        while cur is not None:
            if cur.random is None:
                clone.random = None
            else:
                clone.random = cur.random.next
            cur = cur.next.next
            if clone.next is not None:
                clone = clone.next.next
        cur = pHead
        clone = pHead.next
        while cur is not None:
            cur.next = cur.next.next
            cur = cur.next
            if clone.next is not None:
                clone.next = clone.next.next
            clone = clone.next
        return res
  1. 哈希表

同样的,我们正常拷贝链表节点,只要能够保证我们可以随机访问就行了。因此我们可以考虑哈希表,利用哈希表对链表原始节点和拷贝节点之间建立映射关系,因此原始链表支持随机指针访问,这样我们建立映射以后,可以借助哈希表与原始链表的随机指针,在拷贝链表上随机访问。

  • step 1:建立哈希表,key为原始链表的节点,value为拷贝链表的节点。
  • step 2:遍历原始链表,依次拷贝每个节点,并连接指向后一个的指针,同时将原始链表节点与拷贝链表节点之间的映射关系加入哈希表。
  • step 3:遍历哈希表,对于每个映射,拷贝节点的random指针就指向哈希表中原始链表的random指针。
# -*- coding:utf-8 -*-
# class RandomListNode:
#     def __init__(self, x):
#         self.label = x
#         self.next = None
#         self.random = None
class Solution:
    def Clone(self, pHead):
        if pHead is None:
            return pHead
        res = RandomListNode(0)
        mp = dict()
        cur = pHead
        pre = res  # pre 送进去遍历,遍历结果储存在 res
        while cur is not None:
            clone = RandomListNode(cur.label)
            mp[cur] = clone
            pre.next = clone
            cur = cur.next
            pre = pre.next
        for (key, value) in mp.items():
            if key.random is None:
                value.random = None
            else:
                value.random = mp[key.random]
        return res.next

https://www.nowcoder.com/share/jump/9318638301698721996741

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

LouHerGetUp

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

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

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

打赏作者

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

抵扣说明:

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

余额充值