以下代码是用于搜索数组中元素的最大出现次数的算法。该解决方案假设元素的范围为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作为最多出现的元素,而不是真的。有什么帮助吗?
答案 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相同)。但是,还有另外一个问题,因为违反了输入约束,因为我在下面的评论中解释了原因,因此计数已经关闭。
了解其工作原理的最佳方法是查看另一种算法,虽然看似完全不同,但实际上是同一种算法。另一种算法是:
C[n]
。 (C
for&#34; count&#34;。)A[i]
的每个元素A
并设置C[A[i]] += 1
。由于每个A[i]
介于0和n-1
之间,因此每个C[j]
都介于0和j
之间,当此步骤结束时,任何j
的{{1}}将为数字A[i]
在所有C
中发生值A
的次数。C
中最大元素的位置是A[i]
中最常出现的值(关系是任意解析的)。只需遍历0
即可查找发生的位置并返回结果。现在您发布的算法就是这样,但巧妙地利用了两个事实,这两个事实都依赖于n-1
和A[i]%n
之间A[i]
的原始值:
n
的值将完全等于A[i]
的原始值,无论A[i]/n
被n
添加多少次A[i]
}。A[i]
的值将完全等于n
添加到%n
的次数,与/n
的原始值无关。因此,如果我们通过添加A
而不是1来修改第二个算法,并使用{{1}}和{{1}},就像在您发布的算法中所做的那样,我们可以{{1}用于保存原始值和保存计数。