查找数组中的Majority元素

时间:2013-06-30 08:52:48

标签: algorithm

我想在这里讨论一个我在数据结构书中找到的算法。本书介绍了算法的草图,以便在大小为N的数组中找到多数元素(大于N / 2)。算法草图如下:

首先,找到候选多数元素(这是更难的部分)。这个候选人是唯一可能成为多数元素的元素。第二步确定这个候选人是否实际上是多数。这只是对数组的顺序搜索。 要在数组中找到候选项A,形成第二个数组B.然后比较A1,A2。如果它们相等,则将其中一个添加到B;否则什么也不做。然后比较A3和A4。如果它们相等,再将其中一个添加到B;否则什么也不做。以这种方式继续,直到读取整个数组。然后递归地找到B的候选者;这是A的候选人。

我发现如果N是偶数,算法运行正常。但如果N是奇数怎么办?我们如何处理这个案子?

5 个答案:

答案 0 :(得分:4)

多数元素:

大小为n的数组A []中的多数元素是一个出现超过n / 2次的元素(因此最多只有一个这样的元素)。

寻找候选人:

在O(n)中工作的第一阶段算法称为摩尔投票算法。算法的基本思想是,如果我们用e的所有其他元素抵消元素e的每次出现,那么如果它是多数元素,则e将存在直到结束。

findCandidate(a[], size)
1.  Initialize index and count of majority element
     maj_index = 0, count = 1
2.  Loop for i = 1 to size – 1
    (a)If a[maj_index] == a[i]
        count++
    (b)Else
        count--;
    (c)If count == 0
        maj_index = i;
        count = 1
3.  Return a[maj_index]

上面的算法遍历每个元素并保持[maj_index]的计数,如果下一个元素相同则增加计数,如果下一个元素不相同则递减计数,如果计数达到0则更改maj_index到当前元素并将count设置为1。 第一阶段算法为我们提供了候选元素。在第二阶段,我们需要检查候选人是否真的是多数元素。

第二阶段很简单,可以在O(n)中轻松完成。我们只需要检查候选元素的数量是否大于n / 2。

答案 1 :(得分:1)

大小为n的数组A []中的多数元素是一个出现超过n / 2次的元素

 int find(int[] arr, int size) { 
  int count = 0, i, mElement;
 for (i = 0; i < size; i++) {
    if (count == 0)
        mElement = arr[i];
    if (arr[i] == mElement) 
        count++;
    else
        count--;
  }
 count = 0;
 for (i = 0; i < size; i++)
    if (arr[i] == mElement)
         count++;
  if (count > size/2)
        return mElement;
  return -1;
 }

答案 2 :(得分:0)

您解释过的算法适用于以下想法:

  1. 如果两个连续的元素相等,那么这是潜在的多数元素并将其包含在结果集中(用于进一步处理)

  2. 如果两个元素不同,则此特定对不会决定获胜者。

  3. 第2点是至关重要的 - 假设(A1,A2)对包含多数元素(A1)和另一个少数元素(A2)。删除这一对。 A1在阵列的其余部分仍占多数。

    如果你已经理解了这个解释,那么你就会明白为什么当元素不同时,没有任何东西被添加到B中。

    关于包含奇数个元素的数组的算法的证据就是:向B添加一个奇数元素。原因与#1相同:它可能是多数元素,它应该包含在输出只是为了确保它的计数在此过程中不会丢失。

    无论如何,整个过程可以在没有其他数组B的情况下完成。在这里你可以找到更简单的算法:Finding a Majority Element in an Array

答案 3 :(得分:0)

以下是解决问题的三种算法:

1)扫描数组的元素,使用某种字典(哈希表,平衡树)累积每个不同元素的频率。扫描完成后,选择计数大于n / 2的唯一字典项,或报告没有元素占多数。

2)多数元素必须是数组的中位数(如果存在)。使用五位中值技术或任何其他算法计算中位数,并确认它大于n / 2.

3)Boyer和Moore的算法(与字符串匹配算法相同的人)选择第一个数组元素作为候选项并指定计数为1,然后扫描数组,如果计数加1下一项与当前候选项相同,如果下一项与当前候选项不同,则从计数中减去1,并在计数达到0时将候选项重置为下一个数组元素,计数为1。扫描结束时,如果存在多数,则当前候选人是多数成员,因此需要进行第二次扫描以确认候选人确实占多数。

我在blog上讨论并实现了所有三种算法。

答案 4 :(得分:-1)

我认为当N甚至过时,你的算法也不会起作用。我可以用一个例子来证明:

考虑8个元素的数组,例如2,2,1,1,3,2,2,2。现在根据你的陈述你的B数组将是2,1,2。如果再次重复上述步骤。没有候选人。但这里的实际答案是'2'。所以这种方法肯定是错误的。

Geeks讨论了这个问题。我想这会对你有所帮助:

http://www.geeksforgeeks.org/majority-element/