Algorithm 按重量返回随机物品,高级等级

Algorithm 按重量返回随机物品,高级等级,algorithm,random,Algorithm,Random,有很多典型的问题,比如 想象一下更高级的问题 您有N对(项目id,重量)信息的来源。我们叫他们碎片吧。碎片包含成对的列表(项目id、重量) 这里有中心节点,我们称之为中心节点 问题是:在中央,根据所有权重从大列表(实际上从所有碎片上的所有列表合并而成的列表)中选择随机项 例如,我们有两个碎片: +-------+---------+--------+ |碎片|物品| id |重量| +-------+---------+--------+ | 1 | 1 | 7

有很多典型的问题,比如

想象一下更高级的问题

您有N对
(项目id,重量)
信息的来源。我们叫他们碎片吧。碎片包含成对的列表
(项目id、重量)

这里有中心节点,我们称之为中心节点

问题是:在中央,根据所有权重从大列表(实际上从所有碎片上的所有列表合并而成的列表)中选择随机项

例如,我们有两个碎片:


+-------+---------+--------+
|碎片|物品| id |重量|
+-------+---------+--------+
|   1   |     1   |    7   |
|   1   |     2   |    4   |
|   1   |     3   |    2   |
|   2   |     4   |    5   |
|   2   |     5   |    1   |
+-------+---------+--------+

(让
item_id
在所有碎片中都是唯一的。)

第一个问题

如何随机选择
item\u id
但通过所有碎片加权? 即,
total_weight==7+4+2+5+1==19
,因此选择
1
的概率为7/19、
2
-4/19、
3
-2/19等等

第二个问题

如何随机排列所有碎片中的所有项目,但通过所有碎片进行加权

即,理想范围为:
1,4,2,3,5
(根据其权重)

但可能还有另一个范围,如
1,2,4,3,5
,但频率略低于之前的范围

最坏情况
5,3,2,4,1也可能出现,但概率很小


这在计算机科学中有常见的问题吗?

对于您的第一个问题,您可以执行以下操作

// Your pairs (item_id, weight).
ArrayList<Pair> theBigList;
// The total weight of your data. Get it updated.
int totalWeight;

public int weightedSearch() {
    // Local copy of the value.
    int total = totalWeight;
    Random r = new Random();
    // Random integer in the interval [1 - total]
    int random = r.nextInt(total) + 1;
    for (int i = 0; true; i++) {
        if (theBigList.get(i).weigth < total)
            total -= theBigList.get(i).weigth;
        else
            return theBigLits.get(i).itemId;
    }
}
//您的配对(项目编号、重量)。
arraylistthebiglist;
//数据的总权重。更新它。
总重量;
公共整数加权搜索(){
//值的本地副本。
int total=总重量;
随机r=新随机();
//区间内的随机整数[1-总计]
int random=r.nextInt(总计)+1;
for(int i=0;true;i++){
if(大列表获取(i).weigth<总计)
总计-=大列表。获取(i)。重量;
其他的
返回biglits.get(i).itemId;
}
}
随机搜索(但加权)由生成的随机整数给出。在您的示例中,如果
random
介于1和7之间(7/19 prob.),将返回第一个元素;如果介于8和11之间(4/19 prob.),则返回第二个元素,以此类推

小贴士:从一开始就获取你的重物品,这样你就更有可能更快地返回加权搜索(你的循环在此之前结束)。

我认为你的两个问题是独立的,应该是独立的问题。我也不确定我是否正确理解了它们。但我们要做的是:

分片加权随机查询 如果您对切分的引用涉及到在多个网络主机上分发项目存储并尝试进行某种网络并行随机选择,那么您可以使用我在本文末尾概述的改进算法

该算法最初是为在冗余网络中使用而开发的,在冗余网络中,各种存储主机不一定可以直接从中心主机访问,并且连接是一个图形,而不是一棵树。在这种情况下,您需要能够处理没有响应的主机(这将使单个查询产生偏差,但如果网络故障不频繁且随机,则希望不会使一系列查询产生偏差)。还需要处理主机被查询两次的可能性;在概述的算法中,我简单地忽略了第二个和后续的查询,前提是如果查询到达主机,那么响应可能会返回到查询主机。这可能是完全错误的,但它使问题变得更容易,而且对于足够多的查询,它可能没有偏见

如果中心主机能够可靠地连接到每个存储主机,那么该算法就简单明了,而且没有复杂的问题。中心主机并行查询所有存储主机,每个存储主机返回其存储的对象总权重的元组,以及根据这些权重随机选择的一个对象。(它使用一些标准的加权随机选择算法来实现这一点。使用哪种算法取决于对象和权重的变化频率。)

中央主机维护两个变量:
total
,即已响应的服务器的权重之和(最初为0),以及
候选者
,一个可能返回的随机对象(最初是一些指示“无对象”的哨兵)

它一次处理一个响应,以任何顺序(例如它接收响应的顺序)。对于每个响应,它执行以下操作:

  • 总计
    ← <代码>总计
&plus<代码>重量
  • r
    ← 范围
    [0,总计)
  • 如果
    r
    重量:
    候选人
    ← <代码>对象
  • 当它确定所有远程服务器都已响应时,将返回
    候选

    加权随机洗牌 (至少,我认为您要求的是加权随机洗牌)

    我打算建议使用经过权重修改的标准,我认为这将产生您期望的采样行为。要做到这一点,您可以从任意顺序的对象开始,然后从
    1
    n
    I
    的每个值:

    • 选择
      j
      ,从
      i
      开始的对象中选择(加权)随机元素的索引,然后交换对象
      i
      j
    要做到这一点,您需要维护连续较小后缀的CDF,这可以在O(logn)中通过将对象保持在二叉树中来实现