【问题标题】:Random pairs from two lists来自两个列表的随机对
【发布时间】:2016-07-10 19:21:00
【问题描述】:

我的问题类似于this 一个。

我有两个列表:Xn 元素和 Ym 元素 - 假设它们包含 n x m 矩阵 A 的行和列索引。现在,我想给k 矩阵A 中的随机位置写一些东西。

我想到了两个解决方案:

  1. X 获取随机元素x,从Y 获取随机元素y。检查是否已将某些内容写入A[x][y],如果没有,请写入。但如果k 接近m*n,我可以永远这样拍。
  2. 创建一个包含所有可能的索引组合的m*n 数组,将其随机排列,首先绘制k 元素并在那里写入。但我在这里看到的问题是,如果nm 都非常大,那么新创建的n*m 数组可能巨大(并且洗牌也可能需要一些时间)。李>
  3. Karoly Horvath 建议将两者结合起来。我想我必须选择阈值t 并且:

.

if( k/(m*n) > t ){
    use option 2.
}else{
    use option 1.
}

关于如何选择t 有什么建议吗?

还有其他我错过的(更好的)方法吗?

【问题讨论】:

  • 如果您在开始采样之前知道 k,那将有很大的不同。如果这样做,您可以获得 k 个样本或 n*m-k,以较小者为准。或者您可以对大 k 使用水库采样。

标签: c++ arrays algorithm random permutation


【解决方案1】:

由于 Floyd,有一个 elegant algorithm 用于从一系列整数中进行抽样而不进行替换。您可以将 [0, n*m) 中的结果整数映射到 C++ 函数 [m](int i) { return std::make_pair(i / m, i % m); } 的坐标。

【讨论】:

    【解决方案2】:

    最好的方法取决于你得到的矩阵有多满。如果你要填充一半以上,你的碰撞率(也就是得到已经“写入”到的随机点)将会很高并且会导致您循环播放比您想要的更多。

    我不会生成所有可能性,而是会在您使用列表列表时构建它。一个代表 X 的所有可能值以及 Y 的可能值列表。我将初始化 X 列表而不是 Y 列表。 每次您第一次选择 x 的值时,您都会创建一个字典或 m 元素列表,然后删除您使用的那个。然后下次选择 x 时,您将拥有 m-1 个元素,一旦 X 值用完元素,然后将其从列表中删除,这样就不会再次被选择.. 这样您就可以保证永远不会再次选择占用的空间,并且您不需要生成 n*m 个可能的选项。

    【讨论】:

      【解决方案3】:

      您有 n x m 元素,例如10 x 20 矩阵有 200 个元素。从 200 个中挑选一个应该很容易。关键是,无论您做什么,都可以将两个维度扁平化为一个维度,从而减少这部分问题。

      注意事项:

      • 使用底除法和模运算从索引中取出行和列。
      • 黑名单:将选取的索引存储在一个集合中,以快速跳过那些已经写入的索引。
      • 白名单:将尚未选择的索引存储在集合中。这是否比列入黑名单更好取决于您的设备有多满。
      • 为集合使用正确的容器类型可能很重要,它不必是std::set。对于黑名单,您只需要快速查找和快速插入,vector<bool> 实际上可能工作得很好。对于白名单,您需要快速随机访问和快速删除,带有剩余索引的vector<unsigned> 将是一个不错的选择。
      • 准备根据具体情况在任一方法之间切换。

      【讨论】:

        【解决方案4】:

        对于nxm 矩阵,您可以考虑 [0..n*m-1] 矩阵元素的索引。

        填充一个随机索引比较简单,生成一个0到n*m-1之间的随机数,就是要填充的位置。

        随后执行此操作可能会更棘手:

        1. 你可以测试天气你已经写了一些东西到一个位置并重新生成随机数;但是当您填充矩阵时,您将有更多的索引再生。
        2. 更好的解决方案是将所有索引放在一个包含 n*m 个元素的向量中。生成索引时,将其从列表中删除,下次生成介于 0 和 N-1 之间的随机索引

        示例:

        vector<int> indexVec;
        for (i=0;i<n*m;i++)
            indexVec.push_back(i);
        nrOfIndexes = n*m-1;
        while (nrOfIndexes>1) 
        {
           index = rand()% nrOfIndexes;
           processMatrixLocation(index); 
           indexVec.erase(indexVec.begin()+index);    
           nrOfIndexes--;
        }
        processMatrixLocation(indexVec[0]);
        

        【讨论】:

          猜你喜欢
          • 2019-04-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-04-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多