【leetcode】剑指 Offer 35. 复杂链表的复制

文章介绍了三种方法来复制一个带有随机指针的链表:首先遍历新建节点,再构建next和random指向;其次使用深度优先搜索策略;最后一种方法是先复制节点形成重复链表,再拆分并构建random指针。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本来以为只是多了个random指针,顺着新建节点就好,后来发现next建一个,random指向又建一个,会出错。

以下三种解法都来源于大佬。

今天也是没长脑子的一天呢。

第一种,先把节点都new出来,然后再挨个建立next和random指针的指向。

class Solution:
    def copyRandomList(self, head):
        if not head:
            return None
        cur=head
        dic={}
        #先把节点都new出来
        while cur:
            dic[cur]=Node(cur.val)
            cur=cur.next
        cur=head
        #再构建next和random指向
        while cur:
            dic[cur].next=dic.get(cur.next) #get()返回指定键的值
            dic[cur].random=dic.get(cur.random)
            cur=cur.next
        return dic[head]

第二种,深度优先搜索,还有广度的可以但我没copy

class Solution:
    def copyRandomList(self, head):
        def dfs(head):
            if not head: return None
            if head in visited:
                return visited[head]
            # 创建新结点
            copy = Node(head.val, None, None)
            visited[head] = copy
            copy.next = dfs(head.next)
            copy.random = dfs(head.random)
            return copy
        visited = {}
        return dfs(head)

第三种,画图才看明白的,复制每个节点,此时仍然只有一个链表,只是节点重复两次,比如1->2->3变成了1->1->2->2->3->3,前一个是原有的节点,后一个是新建的节点。然后构建新节点的random指针,再然后把新老两个链表拆开,重新复制next,分成两个链表。

class Solution:
    def copyRandomList(self, head):
        if not head: return
        cur = head
        # 1. 复制各节点,并构建拼接链表
        while cur:
            tmp = Node(cur.val)
            tmp.next = cur.next
            cur.next = tmp
            cur = tmp.next
        #若原链表为1->2->3,则至此链表变为1->1->2->2->3->3
        # 2. 再构建各新节点的 random 指向
        cur = head
        while cur:
            if cur.random:
                cur.next.random = cur.random.next
                #比如1->1->2->2...其中random是2->1,第二个2指向第二个1,跳过原节点
            cur = cur.next.next #原链表节点不需要重新构建random指向,跳过
        # 3. 拆分两链表
        cur = res = head.next #获得copy链表的头res,cur是copy链表的指针
        pre = head #pre代表原节点
        #copy节点和原节点都有了合适的random指向,需要拆开,重构next指向
        #其中pre拆成一个链表,cur拆成一个链表
        while cur.next:
            pre.next = pre.next.next
            cur.next = cur.next.next
            pre = pre.next
            cur = cur.next
        pre.next = None # 单独处理原链表尾节点
        #因为pre比cur靠前一个,当cur.next=None跳出循环时,pre.next实际指向了cur链表的尾节点,所以要单独赋值为None
        return res      # 返回新链表头节点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值