algorithm - 对数组中最大数的索引进行采样,概率为 1/(最大数的数量)

标签 algorithm

这是我最近遇到的面试问题之一。程序返回数组中最大数的索引[注意:数组可能包含也可能不包含最大数的多个副本],这样每个索引(包含最大数)的概率为 1/no of max numbers将被退回。

例子:

  • [-1 3 2 3 3],每个位置[1,3,4]都有1/3的概率返回(三个3)
  • [ 2 4 6 6 3 1 6 6 ],每个[2,3,6,7]都有1/4的概率返回(对应6的位置)。

首先,我给出了 O(n) 时间和 O(n) 空间算法,我在其中收集最大索引集,然后从该集中返回一个随机数。但是他要求一个 O(n) 时间和 O(1) 复杂度的程序,然后我想出了这个。

int find_maxIndex(vector<int> a)
{
     max = a[0];
     max_index = 0;
     count = 0;

     for(i = 1 to a.size())
     {
         if(max < a[i])
         {
             max = a[i];
             count = 0;
         }
         if(max == a[i])
         {
              count++;
              if(rand < 1/count) //rand = a random number in the range of [0,1]
                  max_index = i;
         }
      }
      return max_index;
}

我给了他这个解决方案。但我怀疑这个过程是否会以相等的概率选择最大数字的索引之一。希望我很清楚。还有其他方法可以做到这一点吗?

最佳答案

您拥有的是 Reservoir sampling !还有另一种易于理解的解决方案,但需要两次传递。

int find_maxIndex(vector<int> a){
    int count = 1;
    int maxElement = a[0];
    for(int i = 1; i < a.size(); i++){
        if(a[i] == maxElement){
            count ++;
        } else if(a[i] > maxElement){
            count = 1;
            maxElement = a[i];
        }
    }
    int occurrence = rand() % count + 1;
    int occur = 0;
    for(int i = 0; i < a.size(); i++){
        if(a[i] == maxElement){
            occur++;
            if(occur == occurrence) return i;
        }
    }
}

算法很简单,先求最大元素在第一遍中出现的次数。并选择一个随机事件并返回该事件的索引。虽然需要两次传递,但非常容易理解。

关于algorithm - 对数组中最大数的索引进行采样,概率为 1/(最大数的数量),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21717449/

相关文章:

algorithm - 如何使用 OSRM 计算单源最短路径?

Python:如何按列遍历列表列表,就好像它是一个普通的二维数组(矩阵)一样?

python - 根据 Python 中的另一个列表对列表进行排序

sql - 我正在寻找广播广告调度算法/示例/经验

c - 整数数组的按位异或和移位

algorithm - 拉宾米勒算法

android - 如何编写算法来查看目录是否包含 jpg 文件(子文件夹)

c++ - 如何有效地从 forward_list 中删除一个元素?

algorithm - 从1到N的欧拉Totient函数的有效求和

python - 计算将数组中的值向上或向下舍入以最小影响平均值的点的算法