【面试刷题】水塘抽样算法 | 样本数未知 & 随机取样 & 节省存储空间

简述

水塘抽样是一系列的随机算法,其目的在于从包含n个项目的集合S中选取k个样本,其中n为一很大或未知的数量,尤其适用于不能把所有n个项目都存放到内存的情况。

时间复杂度:O(n)
空间复杂度:O(1)

题目列表

链表随机节点

给你一个单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点 被选中的概率一样 。

实现 Solution 类:

Solution(ListNode head) 使用整数数组初始化对象。
int getRandom()从链表中随机选择一个节点并返回该节点的值。链表中所有节点被选中的概率相等。

  • 解题思路:
    题目解析:
    链表 = 样本数未知
    随机 + 未知 👉 水塘抽样

对第i个节点有:
替换答案的概率是:1/i

证明:
第i个选中的概率=选i后面不中
1/i * 1-(1/i+1)
…… = 1/n (n为样本数)

  • 实现代码:
class Solution:
    def __init__(self, head: Optional[ListNode]):
        self.head = head

    def getRandom(self) -> int:
        node, i, ans = self.head, 1, 0
        while node:
            if randrange(i) == 0:  # 1/i 的概率选中(替换为答案)
                ans = node.val
            i += 1
            node = node.next
        return ans
  • 细节:
    random.randrange ([start,] stop [,step])
    返回 start到stop之间的随机数
    步长为step

randrange(100, 1000, 2) : 976
randrange(100, 1000, 3) : 520

随机数索引

给定一个可能含有重复元素的整数数组,要求随机输出给定的数字的索引。 您可以假设给定的数字一定存在于数组中。

注意:
数组大小可能非常大。 使用太多额外空间的解决方案将不会通过测试。

  • 解题思路:

转化为重复元素中的抽样即可

  • 实现代码:
class Solution:
    def __init__(self, nums: List[int]):
        self.n = nums

    def pick(self, target: int) -> int:
        for i in range((cnt:=0) or len(self.n)):if self.n[i]==target and randrange(cnt:=cnt+1)==0:ans=i
        return ans
  • 细节:
    利用海象运算符进行代码简化
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

赛文X

觉得不错就打赏下呗mua~

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

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

打赏作者

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

抵扣说明:

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

余额充值