在数组中查找最小值所需的分配数量?

时间:2011-07-18 15:55:04

标签: algorithm max

有人问我一个脑筋急转弯,我不知道;我的知识在摊销分析后变慢,在这种情况下,这是O(n)。

public int findMax(array) {
  int count = 0;
  int max = array[0];
  for (int i=0; i<array.length; i++) {
    if (array[i] > max) {
      count++;
      max = array[i];
    }
  } 
  return count;
}

对于大小为n的数组,count的期望值是多少?

从统一分布中随机挑选数字。

4 个答案:

答案 0 :(得分:17)

设f(n)为平均分配数。

然后,如果最后一个元素不是最大元素,则f(n)= f(n-1)。

如果最后一个元素是最大的,那么f(n)= f(n-1)+ 1.

由于最后一个数字最大,概率1/n,而不是最大概率(n-1)/n,我们有:

f(n) = (n-1)/n*f(n-1) + 1/n*(f(n-1) + 1)

展开并收集条款以获取:

f(n) = f(n-1) + 1/n

并且f(1)= 0.所以:

f(1) = 0
f(2) = 0 + 1/2
f(3) = 0 + 1/2 + 1/3
f(4) = 0 + 1/2 + 1/3 + 1/4

即,f(n)是第n个“谐波数”,您只能以封闭形式获得approximately。 (好吧,比第n个谐波数少一个。如果你将max初始化为INT_MIN并让循环运行,那么问题会更漂亮,因此f(1)= 1。)

以上并不是一个严格的证据,因为我对预期值与实际值的关系很草率。但我相信答案是正确的: - )。

答案 1 :(得分:16)

我想对Nemo的答案发表评论,但我没有评论的声誉。他的正确答案可以简化:

第二个数字大于第一个的可能性是1/2。无论如何,第三个数字大于之前的几率是1/3。这些都是独立的机会,因此总的期望是

1/2 + 1/3 + 1/4 + .. + 1 / n

答案 2 :(得分:1)

当每个项目的值来自有限集时,您实际上可以进一步进行此分析。设E(N,M)是从大小为M的字母表中找到N个元素的最大值时的预期分配数。然后我们可以说......

E(0, M) = E(N, 0) = 0
E(N, M) = 1 + SUM[SUM[E(j, i) * (N - 1 Choose j) * ((M - i) / M)^(N-j-1) * (i / M) ^ j : j from 0 to N - 1] : i from 0 to M - 1]

这有点难以提出封闭形式,但我们可以确定E(N,M)在O(log(min(N,M)))。这是因为E(N,INF)在THETA(log(N))中,因为谐波序列和与log函数成比例增长并且E(N,M)<1。 E(N,M + 1)。同样,当M < N我们有E(N,M)&lt; E(M,INF),因为有M个唯一值。

这里有一些自己计算E(N,M)的代码。我想知道是否有人可以把它变成封闭的形式?

#define N 100
#define M 100

double NCR[N + 1][M + 1];
double E[N + 1][M + 1];

int main() {
  NCR[0][0] = 1;
  for(int i = 1; i <= N; i++) {
    NCR[i][0] = NCR[i][i] = 1;
    for(int j = 1; j < i; j++) {
      NCR[i][j] = NCR[i - 1][j - 1] + NCR[i - 1][j];
    }
  }

  for(int n = 1; n <= N; n++) {
    for(int m = 1; m <= M; m++) {
      E[n][m] = 1;
      for(int i = 1; i < m; i++) {
        for(int j = 1; j < n; j++) {
          E[n][m] += NCR[n - 1][j] *
                     pow(1.0 * (m - i) / m, n - j - 1) *
                     pow(1.0 * i / m, j) * E[j][i] / m;
        }
      }
    }
  }
  cout << E[N][M] << endl;
}

答案 3 :(得分:0)

我假设所有元素都是不同的,并在for循环之外计算max的初始赋值。

如果数组按递增顺序排序,变量max将被精确分配n次(每次获得更大的值)。

如果数组按降序排序,变量max将被分配一次(第一次分配,后面的所有值都更小)。

编辑: 正如评论中所指出的,我对随机置换阵列的表述实际上是错误的。我想@Nemo会发布正确答案。

我认为只计算作业的数量并不能真正衡量这项功能的成本。无论我们是否实际更新max的值,我们实际上比较正好n次。因此,较少的任务并不意味着完成的工作量减少了。

另请注意,实际上没有交换。只有作业和比较。