经典概率题 之 随机算法之水塘抽样算法

题目:
给你一个未知长度的链表,请你设计一个算法,只能遍历一次,随机地返回链表中的一个节点。

LeetCode 382 和 398 题,水塘抽样算法(Reservoir Sampling),本质上是一种随机概率算法。

382题 链表随机节点:

382. 链表随机节点
给定一个单链表,随机选择链表的一个节点,并返回相应的节点值。保证每个节点被选的概率一样。

进阶:
如果链表十分大且长度未知,如何解决这个问题?你能否使用常数级空间复杂度实现?

示例:
// 初始化一个单链表 [1,2,3].
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
Solution solution = new Solution(head);
// getRandom()方法应随机返回1,2,3中的一个,保证每个元素被返回的概率相等。
solution.getRandom();

一遍遍历,这个很重要。
code:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def __init__(self, head):
        self.head = head

    def getRandom(self):
        """
        Returns a random node's value.
        :rtype: int
        """
        self.res = self.head
        i = 0
        ret = 0
        while self.res:
            a = random.randint(0,i)
            if a==0:
                ret = self.res.val
            i += 1
            self.res = self.res.next
        return ret

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

证明:
在这里插入图片描述
参考链接

这个证明,真的是这个题的核心。主要思想就是,有多少概率选则当前值,如果选了,有多少概率不被替换。最后发现选了+不被替换的概率刚好是1/n。
证明要多想想,挺不错的。

接下来看一个几乎一样的题。
leetcode 398题 随机数索引:

398. 随机数索引
给定一个可能含有重复元素的整数数组,要求随机输出给定的数字的索引。 您可以假设给定的数字一定存在于数组中。
注意:
数组大小可能非常大。 使用太多额外空间的解决方案将不会通过测试。

示例:
int[] nums = new int[] {1,2,3,3,3};
Solution solution = new Solution(nums);
// pick(3) 应该返回索引 2,3 或者 4。每个索引的返回概率应该相等。
solution.pick(3);
// pick(1) 应该返回 0。因为只有nums[0]等于1。
solution.pick(1);

code:

class Solution(object):

    def __init__(self, nums):
        """
        :type nums: List[int]
        """
        self.nums = nums
        

    def pick(self, target):
        """
        :type target: int
        :rtype: int
        """
        ret = -1
        i = 0
        for r, num in enumerate(self.nums):
            if target==num:
                a = random.randint(0,i)
                if a==0:
                    ret = r
                i += 1
        return ret    

# Your Solution object will be instantiated and called as such:
# obj = Solution(nums)
# param_1 = obj.pick(target)

好了,这个题挺有意思。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值