【问题标题】:Filling up an array randomly随机填充数组
【发布时间】:2017-06-04 23:11:26
【问题描述】:
我正在寻找通过调用 add() 在随机空位置填充数组的数据结构。一旦一个位置被填满,它就不能被另一个 add() 覆盖。调用 remove(i) 释放 A[i] 处的位置。可以混合调用 add() 和 remove()。
我的第一个想法是每次调用 add() 时随机生成一个介于 0 和 n-1 之间的数字。如果是空的,填满它;如果它已满,则进行顺序搜索,直到找到一个空的。然而,这有两个问题:1)如果数组大部分是满的,它将花费接近 O(n) 时间 2)随机选择将不均匀。
我的第二个想法是对数字 1 到 n-1 使用随机播放并按此顺序添加,但是这不支持 remove()。
有没有一种方法可以保证 add() 和 remove() 的持续性能?
【问题讨论】:
标签:
arrays
algorithm
performance
random
data-structures
【解决方案1】:
我们将要填充的数组称为work_array[]。使用两个辅助数组filled_positions[] 和empty_positions[],包含work_array[] 中的索引,以及两个计数器num_filled 和num_empty,给出filled_positions[] 和empty_positions[] 中的元素数。假设数组从 0 开始索引,最初 num_filled 是 0,empty_positions[] 包含 0、1、2、... 到 n - 1,而 num_empty 是 n。
-
在随机位置添加元素:
- 在
0 和num_empty - 1 之间生成一个随机数r。
- 从
empty_positions[r]中选择索引i。
- 如果 r 小于
num_empty - 1,则将 empty_positions[r] 设置为 empty_positions[num_empty-1]。
- 递减
num_empty。
- 将
filled_positions[num_filled] 设置为i。
- 递增
num_filled。
- 在
work_array[i]处填充元素。
-
从随机位置移除元素:
- 在
0 和num_filled - 1 之间生成一个随机数r。
- 从
filled_positions[r]中选择索引i。
- 如果 r 小于
num_filled - 1,则将filled_positions[r] 设置为filled_positions[num_filled-1]。
- 递减
num_filled。
- 将
empty_positions[num_empty] 设置为i。
- 递增
num_empty。
您可能想要维护一个位数组work_array_map[],如果work_array[i] 被填充,则work_array_map[i] 为1,否则为0。使用work_array_map[],您可以判断元素 i 是否在恒定时间内被填充。
【解决方案2】:
您可以为填充和空数组位置保留一个单独的链接列表。现在生成一个介于 0 到(考虑的链表长度,即填充或空)之间的随机数,并使用它从列表中选择一个随机位置。
现在,如果您从填充列表中选择任何元素,则删除相应的条目并将其添加到空列表中。
当然,链表的遍历将花费 O(链表的长度)时间,但这消除了在 add() 时选择填充位置或在 remove() 时选择空位置的问题。