返回
随机数索引:从有序数组中随机抽样
后端
2024-02-21 20:53:12
问题背景
在软件开发过程中,我们经常需要从数据集中随机抽取样本。一个常见的需求是从一个有序数组中随机选择一个特定的目标值。假设我们有一个有序数组nums
,我们需要实现一个Solution
类,该类的构造函数接收nums
作为参数,并支持一个pick
方法,该方法能够从nums
中随机选择一个等于target
的目标数字。如果有多个这样的数字,则返回其中一个;若不存在,则返回-1
。
蓄水池抽样算法
为了解决这个问题,我们可以使用一种称为蓄水池抽样的算法。蓄水池抽样是一种用于从一个未知大小的数据集中随机选择k个元素的算法。在这个问题中,我们可以将其扩展为只选择一个元素。
算法步骤
- 遍历数组:从头到尾遍历数组
nums
。 - 计算概率:对于每个元素
nums[i]
,计算它被选中的概率,即1 / (i + 1)
。 - 随机选择:生成一个介于
0
到i
之间的随机数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
每次运行结果可能不同,因为选择是随机的。
总结
通过使用蓄水池抽样算法,我们可以高效地从有序数组中随机选择一个特定的目标值。这种方法不仅时间复杂度低,而且空间复杂度也非常低,非常适合处理大规模数据集。在实际应用中,开发者可以根据具体需求调整算法,例如选择多个元素或处理更复杂的数据结构。
相关资源
通过理解和应用蓄水池抽样算法,开发者可以更好地解决类似的随机抽样问题,提高代码的效率和可维护性。