查找元素,数组语法的最大出现次数

时间:2014-09-22 06:39:09

标签: c algorithm search

以下代码是用于搜索数组中元素的最大出现次数的算法。该解决方案假设元素的范围为0到n-1。

void MaxRepetitions( int A[], int n ) {

int i=0; max=0, maxIndex;

for(i=0, i<n, i++) 
    A[A[i]%n] +=n;

for( i=0, i<n, i++)

    if (A[i]/n > max) { 
       max = A[i]/n;
       maxIndex=i;

}

return maxIndex;
}

A[A[i]%n] +=n;如何扩展?

A[A[i]%n] = A[A[i]%n] + n是否正确?

-

修改

对于A = [2,4,7,5,4,11]的例子,其中n = 6

A[0]%n = 2
A[1]%n = 4
A[2]%n = 1
A[3]%n = 5
A[4]%n = 4
A[5]%n = 5

此循环后:

for(i=0, i<n, i++) 
    A[A[i]%n] = A[A[i]%n] + n;

Iteration 1: 

A[A[0]%n] = A[A[0]%n] + 6   --> A[2] = A[2] + 6  --> A[2] = 13

The array is now: A = [2, 4, 13, 5, 4, 11]

Iteration 2:

A[A[1]%n] = A[A[1]%n] + 6   --> A[4] = A[4] + 6  --> A[4] = 10

The array is now: A = [2, 4, 13, 5, 10, 11]


Iteration 3:

A[A[2]%n] = A[A[2]%n] + 6   --> A[1] = A[1] + 6  --> A[1] = 10

The array is now: A = [2, 10, 13, 5, 10, 11]

Iteration 4:

A[A[3]%n] = A[A[3]%n] + 6   --> A[5] = A[5] + 6  --> A[5] = 17

The array is now: A = [2, 10, 13, 5, 10, 17]

Iteration 5:

A[4] now is 10

A[A[4]%n] = A[A[4]%n] + 6   --> A[4] = A[4] + 6  --> A[4] = 16

The array is now: A = [2, 10, 13, 5, 16, 17]

Iteration 6:

A[5] now is 17

A[A[5]%n] = A[A[5]%n] + 6   --> A[5] = A[5] + 6  --> A[5] = 23

现在阵列:A = [2,10,13,5,16,23]

现在,一旦第二个循环运行,每个元素的A [i] / n为:A [0,1,2,0,2,3]

看起来这个算法会选择11作为最多出现的元素,而不是真的。有什么帮助吗?

3 个答案:

答案 0 :(得分:0)

此:

A[A[i]%n] +=n

扩展为等同于:

A[A[i]%n] = A[A[i]%n] + n

外,副作用仅评估一次。换句话说,如果左表达式使用了具有++--这样的副作用的运算符,那么这些副作用只会发生一次,与您实际写出的情况相反。整个x = x + y表达式,x中的副作用将被评估两次。

答案 1 :(得分:0)

A [A [i]%n] + = n

A[i]           : value contained in array A at position i
A[i]%n         : remainder of dividing this value by n (used to not allow this index go beyond the size of A
A[A[i]%n]      : the value contained in that new position
A[A[i]%n] += n : add n to this value

数字示例

A[3] = {7, 10, 24}
n = 3

i = 0
A[A[0]%3] = A[7%3] // 7 = 2*3 + 1
          = A[1]
          = 10
add 3 ==> A[1] = 13

i = 1
A[A[1]%3] = A[13%3] // 13 = 4*3 +1
          = A[1]
          = 13
add 3 ==> A[1] = 16

i = 2
A[A[2]%3] = A[24%3] // 24 = 8*3 + 0
          = A[1]
          = 7
add 3 ==> A[1] = 10

答案 2 :(得分:0)

正如其他人所说,<anything> += <value>相当于<anything> = <anything> + <value>,但<anything>只评估一次。

您对算法运行的分析是正确的,但问题是输入违反了所有元素在0和n-1之间的规定约束。实际上,由于11%6 = 5,算法产生的答案并不完全错误(模6,值5出现的值与值4相同)。但是,还有另外一个问题,因为违反了输入约束,因为我在下面的评论中解释了原因,因此计数已经关闭。

了解其工作原理的最佳方法是查看另一种算法,虽然看似完全不同,但实际上是同一种算法。另一种算法是:

  1. 分配一个单独的数组C[n]。 (C for&#34; count&#34;。)
  2. 循环遍历A[i]的每个元素A并设置C[A[i]] += 1。由于每个A[i]介于0和n-1之间,因此每个C[j]都介于0和j之间,当此步骤结束时,任何j的{​​{1}}将为数字A[i]在所有C中发生值A的次数。
  3. 因此,C中最大元素的位置A[i]中最常出现的值(关系是任意解析的)。只需遍历0即可查找发生的位置并返回结果。
  4. 现在您发布的算法就是这样,但巧妙地利用了两个事实,这两个事实都依赖于n-1A[i]%n之间A[i]的原始值:

    1. n的值将完全等于A[i]原始值,无论A[i]/nn添加多少次A[i] }。
    2. A[i]的值将完全等于n添加到%n的次数,与/n的原始值无关。
    3. 因此,如果我们通过添加A而不是1来修改第二个算法,并使用{{1}}和{{1}},就像在您发布的算法中所做的那样,我们可以{{1}用于保存原始值和保存计数。