数据结构- 链表的应用【1】

复制带随机指针的链表

题目

给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。

要求返回这个链表的 深拷贝。

我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

val:一个表示 Node.val 的整数。
random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。

这个题目, 主要时考察链表的应用, 同时这个题目还是很有创新性的, 加入了随机指针, 而且用深拷贝链表。

这个题目拿出来将的主要目的就是想扩展下思路,
下面这三种方法都是很好的, 尤其是第一种, 第二种算法也是很好的, 第三种也不错。

方法一:O(1)空间复杂度

这个思路很简单, 但是还是要注意一些细节

  • 首先遍历给定的链表, 在原始链表每个节点i的旁边拷贝一个新的节点j, 然后i的后一个节点指向j,然后j的next指向原来i的next节点。
    在这里插入图片描述

  • 然后遍历新生成的这个链表, 将新节点的random指针指向对应的位置, 即也就是将上图中节点A’, B’ , C’的random指向A, B , C的random的next

在这里插入图片描述

  • 最后就是解除节点N到N‘之间的连接, 建立起正确的next关系。
    在这里插入图片描述
"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""

class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        # print(head.next.next.val)
        if head is None:
            return head
        point = head
        while point:
            node = Node(point.val, point.next, None)
            point.next = node
            point = node.next
        # print("****")
        res = head.next
        point_1= head
        while point_1:
            if point_1.random != None:
                point_1.next.random = point_1.random.next
            else: point_1.next.random = None
            point_1 = point_1.next.next
        
        point_old, point_new = head, head.next
        while point_old:
            point_old.next = point_old.next.next if point_old.next else None
            point_new.next = point_new.next.next if point_new.next else None
            point_old, point_new = point_old.next, point_new.next
        return res
方法二:回溯

主要是将next和random指针平等对待, 用递归的算法实现, (DFS)

可以去参考我前一篇博客【DFS和BFS】

class Solution(object):
    """
    :type head: Node
    :rtype: Node
    """
    def __init__(self):
        # Dictionary which holds old nodes as keys and new nodes as its values.
        self.visitedHash = {}

    def copyRandomList(self, head):

        if head == None:
            return None

        # If we have already processed the current node, then we simply return the cloned version of it.
        if head in self.visitedHash:
            return self.visitedHash[head]

        # create a new node
        # with the value same as old node.
        node = Node(head.val, None, None)

        # Save this value in the hash map. This is needed since there might be
        # loops during traversal due to randomness of random pointers and this would help us avoid them.
        self.visitedHash[head] = node

        # Recursively copy the remaining linked list starting once from the next pointer and then from the random pointer.
        # Thus we have two independent recursive calls.
        # Finally we update the next and random pointers for the new node created.
        node.next = self.copyRandomList(head.next)
        node.random = self.copyRandomList(head.random)

        return node
方法三:O(N)空间复杂度

这个思路也挺清晰的:

  • 首先是遍历这个链表
  • 我们首先用一个字典D去存储我们已经访问过的节点信息,对遍历中的每个节点, 我们先去查询D中有没有其信息, 如果有的话, 我们就不用创建节点, 然后配置其节点的random 和 next指针, 没有的话, 我们就创建一个节点, 然后将节点信息加入D中, 表示我们已经访问过该节点。
  • 对于random指针和next指针, 我们要求查询它们指向的节点有没有在字典D中, 如果有的, 直接取值, 没有的话就创建节点,然后将节点信息加入D中, 表示我们已经访问过该节点。
"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""

class Solution:
    def __init__(self):
        self.visited = {}
    def getCloneNode(self, node):
        if node:
            if node in self.visited:
                return self.visited[node]
            
            else:
                self.visited[node] = Node(node.val, None, None)
                return self.visited[node]
        return None
    
    def copyRandomList(self, head: 'Node') -> 'Node':
        if not head:
            return head
        
        old_node = head
        
        new_node = Node(old_node.val, None, None)
        
        self.visited[old_node] = new_node
        
        while old_node != None:
            
            new_node.random = self.getCloneNode(old_node.random)
            new_node.next = self.getCloneNode(old_node.next)
            
            old_node =old_node.next
            new_node = new_node.next
        return self.visited[head]

参考文献:
【1】Leecode-138-138. 复制带随机指针的链表-官方题解
【2】【DFS和BFS】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值