剑指Offer 35. 复杂链表的复制(Medium)/ 【水塘抽样】382. 链表随机节点(M)/ 398. 随机数索引(M) /(深拷贝)克隆图(M)/ 飞机座位概率 / 按权重随机选择

在这里插入图片描述
在这里插入图片描述
【题目链接】

题解

  1. 复杂链表的复制(哈希表 / 拼接与拆分,清晰图解)
  2. 图解 链表的深拷贝

思路

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码

"""
# 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:
    ### 1130 哈希表(60 ms,14.2 MB)
    def copyRandomList(self, head: 'Node') -> 'Node':
        # 若head为空,直接返回
        if not head: return 

        # 第一次遍历链表:构建哈希表,用于存放 '原节点:复制的新节点'
        dic = {}
        cur = head
        while cur:
            dic[cur] = Node(cur.val)
            cur = cur.next
        
        # 第二次遍历链表:构建新节点的 next 和 random 指向
        cur = head
        while cur:
            dic[cur].next = dic.get(cur.next)
            dic[cur].random = dic.get(cur.random)
            cur = cur.next
        
        return dic[head] # 返回新链表的头节点

	# 方法二:拼接 + 拆分
    def copyRandomList(self, head: 'Node') -> 'Node':
        if not head: return
        cur = head
        # 1. 复制各节点,并构建拼接链表
        while cur:
            tmp = Node(cur.val)
            tmp.next = cur.next
            cur.next = tmp
            cur = tmp.next
        # 2. 构建各新节点的 random 指向
        cur = head
        while cur:
            if cur.random:
                cur.next.random = cur.random.next
            cur = cur.next.next
        # 3. 拆分两链表
        cur = res = head.next
        pre = head
        while cur.next:
            pre.next = pre.next.next
            cur.next = cur.next.next
            pre = pre.next
            cur = cur.next
        pre.next = None # 单独处理原链表尾节点
        return res      # 返回新链表头节点

382. 链表随机节点

在这里插入图片描述

import random
class Solution:

    def __init__(self, head: ListNode):
        self.head = head
        
    def getRandom(self) -> int:
        count = 0
        reserve = 0
        cur = self.head
        
        while cur:
            count += 1
            rand = random.randint(1,count)
            if rand == count:
                reserve = cur.val
            cur = cur.next
            
        return reserve

133. (深拷贝)克隆图(M)

在这里插入图片描述
在这里插入图片描述

"""
# Definition for a Node.
class Node:
    def __init__(self, val = 0, neighbors = None):
        self.val = val
        self.neighbors = neighbors if neighbors is not None else []
"""

# from typing import Optional
class Solution:
    def __init__(self):
        self.visited = {}

    def cloneGraph(self, node):
        if not node:
            return node

        # 如果该节点已经被访问过了,则直接从哈希表中取出对应的克隆节点返回
        if node in self.visited:
            return self.visited[node]

        # 克隆节点,注意到为了深拷贝我们不会克隆它的邻居的列表
        clone_node = Node(node.val, [])

        # 哈希表存储
        self.visited[node] = clone_node

        # 遍历该节点的邻居并更新克隆节点的邻居列表
        if node.neighbors:
            clone_node.neighbors = [self.cloneGraph(n) for n in node.neighbors]

        return clone_node

在这里插入图片描述

  • BFS
    在这里插入图片描述
    在这里插入图片描述

398. 随机数索引

在这里插入图片描述

class Solution:
	# 哈希表
    def __init__(self, nums: List[int]):
        self.pos = defaultdict(list)
        for i, num in enumerate(nums):
            self.pos[num].append(i)

    def pick(self, target: int) -> int:
        import random
        
        return random.choice(self.pos[target])

# Your Solution object will be instantiated and called as such:
# obj = Solution(nums)
# param_1 = obj.pick(target)
  • 法二(水塘抽样,写法1,推荐)
    在这里插入图片描述

  • 法二(水塘抽样,写法2)
    在这里插入图片描述

1227. 飞机座位分配概率

在这里插入图片描述

  • 官方题解
    在这里插入图片描述
    在这里插入图片描述
  • 动态规划(一个错误使用动态规划的例子)
    在这里插入图片描述
    在这里插入图片描述

528. 按权重随机选择

在这里插入图片描述

class Solution:

    def __init__(self, w: List[int]):
        n = len(w)
        self.prefix_sum = [0] * n
        self.prefix_sum[0] = w[0]

        # 前缀和
        for i in range(1, n):
            self.prefix_sum[i] = self.prefix_sum[i-1] + w[i]
        # print(self.prefix_sum)

    def pickIndex(self) -> int:
        seed = random.randint(1, self.prefix_sum[-1])
        index = bisect_left(self.prefix_sum, seed)
        return index

# Your Solution object will be instantiated and called as such:
# obj = Solution(w)
# param_1 = obj.pickIndex()

在这里插入图片描述

class Solution:

    def __init__(self, w: List[int]):
        self.w = w
        self.maxv = sum(w)

    def pickIndex(self) -> int:
        x = random.randint(1,self.maxv)
        for i in range(0,len(self.w)):
            x -= self.w[i]
            
            if x <= 0:
                return i

# Your Solution object will be instantiated and called as such:
# obj = Solution(w)
# param_1 = obj.pickIndex()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值