返回

随机数索引:从有序数组中随机抽样

后端

问题背景

在软件开发过程中,我们经常需要从数据集中随机抽取样本。一个常见的需求是从一个有序数组中随机选择一个特定的目标值。假设我们有一个有序数组nums,我们需要实现一个Solution类,该类的构造函数接收nums作为参数,并支持一个pick方法,该方法能够从nums中随机选择一个等于target的目标数字。如果有多个这样的数字,则返回其中一个;若不存在,则返回-1

蓄水池抽样算法

为了解决这个问题,我们可以使用一种称为蓄水池抽样的算法。蓄水池抽样是一种用于从一个未知大小的数据集中随机选择k个元素的算法。在这个问题中,我们可以将其扩展为只选择一个元素。

算法步骤

  1. 遍历数组:从头到尾遍历数组nums
  2. 计算概率:对于每个元素nums[i],计算它被选中的概率,即1 / (i + 1)
  3. 随机选择:生成一个介于0i之间的随机数j。如果j小于等于1 / (i + 1),则用nums[i]替换当前选中的元素。

代码实现

以下是使用Python实现的代码示例:

import random

class Solution:

    def __init__(self, nums):
        self.nums = nums

    def pick(self, target):
        reservoir = None
        count = 0
        for i, num in enumerate(self.nums):
            if num != target:
                continue
            count += 1
            if random.random() < 1 / count:
                reservoir = num
        return reservoir if reservoir is not None else -1

分析

  • 时间复杂度O(n),其中n是数组nums的长度。我们只需要遍历一次数组。
  • 空间复杂度O(1),我们只需要存储一个变量来保存选中的元素。

示例

假设我们有以下数组:

nums = [1, 2, 3, 3, 3, 5]
solution = Solution(nums)
for i in range(10):
    print(solution.pick(3))

输出可能是:

3
3
3
3
3
3
3
3
3
3

每次运行结果可能不同,因为选择是随机的。

总结

通过使用蓄水池抽样算法,我们可以高效地从有序数组中随机选择一个特定的目标值。这种方法不仅时间复杂度低,而且空间复杂度也非常低,非常适合处理大规模数据集。在实际应用中,开发者可以根据具体需求调整算法,例如选择多个元素或处理更复杂的数据结构。

相关资源

通过理解和应用蓄水池抽样算法,开发者可以更好地解决类似的随机抽样问题,提高代码的效率和可维护性。