简体   繁体   English

数据结构为 select 数字,概率与其值成正比,时间复杂度小于 O(n)

[英]Data structure to select number with probability proportional to its value in less than O(n)

I have a set of numbers, [1, 3, 4, 5, 7] .我有一组数字[1, 3, 4, 5, 7] I want to select a number from the set with a probability proportional to its value:我想要 select 中的一个数字,其概率与其值成正比:

Number数字 Probability可能性 % %
1 1个 1/20 1/20 5 5个
3 3个 3/20 3/20 15 15
4 4个 4/20 4/20 20 20
5 5个 5/20 5/20 25 25
7 7 7/20 7/20 35 35

However, I want to be able to both update and query this set in less than O(n).但是,我希望能够在小于 O(n) 的时间内更新和查询这个集合。 Are there any data structures that would help me achieve that?是否有任何数据结构可以帮助我实现这一目标?

Preferably in Java, if it exists already最好在Java,如果已经存在

You can get O(log n) amortized querying and updating (including removing/inserting elements) using a Binary Indexed Tree , also known as a Fenwick tree.您可以使用Binary Indexed Tree (也称为 Fenwick 树)获得O(log n)分摊查询和更新(包括删除/插入元素)。 The idea is to use dynamic resizing , which is the same trick used in variable-size arrays and hash tables to get amortized constant time appends.这个想法是使用动态调整大小,这与可变大小 arrays 和 hash 表中使用的相同技巧来获得摊销的常量时间追加。 This also implies that you should be able to get O(log n) worst-case bounds using the method from dynamic arrays of rebuilding a second array on the side, but this makes the code significantly longer.这也意味着您应该能够使用动态 arrays 中重建第二个数组的方法获得O(log n)最坏情况界限,但这会使代码明显变长。

First, we know that given a list of the partial sums of arr , and a random integer in [0, sum(arr)] , we can do this in O(log n) time with a binary search.首先,我们知道给定arr的部分和列表,以及[0, sum(arr)]中的随机 integer,我们可以使用二分查找在O(log n)时间内完成此操作。 Specifically, if our random integer is r , we want the index of the rightmost partial sum less than or equal to r .具体来说,如果我们的随机 integer 是r ,我们希望最右边的部分和的索引小于或等于r

Now, we'll use the technique from this post of Fenwick trees to maintain and query the partial sums.现在,我们将使用这篇 Fenwick 树帖子中的技术来维护和查询部分和。 That post is slightly different from yours: they have a fixed set of n keys, whose weights can be updated, without new insertions or deletions.该帖子与您的帖子略有不同:它们有一组固定的n键,可以更新其权重,而无需新的插入或删除。

A Fenwick tree is an array that allows you to answer queries about partial sums of a 'base' array in O(log n) time per query, and can be built in O(n) time. Fenwick 树是一个数组,允许您在每次查询的O(log n)时间内回答有关“基本”数组的部分和的查询,并且可以在O(n)时间内构建。 In particular, you can特别是,你可以

  1. Find the the index of the rightmost partial sum of arr less than or equal to r ,找到arr小于或等于r的最右边部分和的索引,
  2. Set arr[i] to arr[i]+c for any integer c ,将任何 integer carr[i]设置为arr[i]+c

both in O(log n) time.都在O(log n)时间内。

Start by appending n zeros to arr (it is now half full), and build its Fenwick tree.首先向arr添加n零(它现在是半满的),然后构建它的 Fenwick 树。 We can treat 'removing' an element as setting its weight to 0. Inserting an element is done by taking the zero after the rightmost nonzero element in arr as the new element's spot.我们可以将“删除”一个元素视为将其权重设置为 0。插入一个元素是通过将arr中最右边的非零元素之后的零作为新元素的位置来完成的。 The removed elements and new elements may eventually cause our array to fill up: if we reach 75% capacity, rebuild our array and Fenwick tree, doubling the array size (pad with zeros on the right) and deleting all the zero-weight elements.删除的元素和新元素最终可能会导致我们的数组填满:如果我们达到 75% 的容量,重建我们的数组和 Fenwick 树,将数组大小加倍(在右侧填充零)并删除所有零权重元素。 If we reach 25% capacity, shrink the array to half size, rebuilding the Fenwick tree as well.如果我们达到 25% 的容量,将阵列缩小一半,同时重建 Fenwick 树。

You'll need to maintain arr constantly to be able to rebuild, so all updates must be done on arr and the Fenwick tree.您需要不断维护arr才能重建,因此所有更新都必须在arr和 Fenwick 树上完成。 You'll also need a hashmap from array indices to your keys for random selection.您还需要一个 hashmap 从数组索引到您的键以进行随机选择。

The good part is that you don't need to modify the Fenwick tree internals at all: given a Fenwick tree implementation in Java that supports initialization, array updates and the binary search, you can treat it as a black box.好处是您根本不需要修改 Fenwick 树的内部结构:给定 Java 中支持初始化、数组更新和二进制搜索的 Fenwick 树实现,您可以将其视为黑盒。 This stops being true if you want worst-case time guarantees: then, you'll need to copy the internal state of the Fenwick tree, piece by piece, which has some complications.如果你想要最坏情况下的时间保证,这就不再成立了:然后,你需要逐个复制 Fenwick 树的内部 state,这有一些复杂性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在不到O(n)的时间内获得数据结构中元素之间的最小差异 - Get the smallest difference between elements in a data structure in less than O(n) time 查找数组在小于O(n ^ 2)内重复的次数 - Find the number of times a number is repeated in an array in less than O(n^2) 使用数据结构在O(n)中解决这个问题 - Using a data structure to solve this in O(n) 从排序数组中查找小于O(n)的唯一数字 - Finding unique numbers from sorted array in less than O(n) 找到小于O(N)的序列的第n项 - Find nth term of a sequence in less than O(N) 是否可以使嵌套的for循环小于O(N ^ 2)? - Is it possible to make this nested for loop less than O(N^2)? 在小于 O(n^2) 的范围内对给定的整数列表进行排名 - Ranking a given list of integers in less than O(n^2) 有没有办法在少于 O(n) 的时间内连接 Java 字符串? - Is there a way to concatenate Java strings in less than O(n) time? 如何根据Map中的Integer值相对于O(n)时间内的其他值随机选择一个键? - How to randomly select a key based on its Integer value in a Map with respect to the other values in O(n) time? 使用O(log(n))插入和O(1)查找排序数据结构 - Sorted Data Structure with O(log(n)) insert and O(1) lookup
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM