大小为n的数组,其中一个元素为n / 2次

时间:2009-04-13 18:59:02

标签: algorithm

给定n个整数数组,其中一个元素出现的次数超过n / 2次。我们需要在线性时间和恒定的额外空间中找到该元素。

YAAQ:又一个阵列问题。

9 个答案:

答案 0 :(得分:22)

我有一种潜行的怀疑,这是(在C#中)

// We don't need an array
public int FindMostFrequentElement(IEnumerable<int> sequence)
{
    // Initial value is irrelevant if sequence is non-empty,
    // but keeps compiler happy.
    int best = 0; 
    int count = 0;

    foreach (int element in sequence)
    {
        if (count == 0)
        {
            best = element;
            count = 1;
        }
        else
        {
            // Vote current choice up or down
            count += (best == element) ? 1 : -1;
        }
    }
    return best;
}

这听起来不太可行,但确实如此。 (Proof as a postscript file,由Boyer / Moore提供。)

答案 1 :(得分:7)

找到中位数,在未排序的数组上需要O(n)。由于超过n / 2个元素等于相同的值,因此中位数也等于该值。

答案 2 :(得分:2)

int findLeader(int n, int* x){
    int leader = x[0], c = 1, i;
    for(i=1; i<n; i++){
        if(c == 0){
            leader = x[i];
            c = 1;
        } else {
            if(x[i] == leader) c++;
            else c--;
        }
    }

    if(c == 0) return NULL;
    else {
        c = 0;
        for(i=0; i<n; i++){
            if(x[i] == leader) c++;
        }
        if(c > n/2) return leader;
        else return NULL;
    }
}

我不是此代码的作者,但这可以解决您的问题。第一部分寻找潜在的领导者,第二部分检查它是否在阵列中出现超过n / 2次。

答案 3 :(得分:1)

嗯,你可以按照here[pdf]描述进行inplace radix排序,这不需要额外的空间和线性时间。然后你可以进行单次通过计数连续元素并终止计数&gt; N / 2。

答案 4 :(得分:1)

这是我最初的想法。

我试图保持不变量“一个元素出现超过n / 2次”,同时减少问题集。

让我们开始比较[i],[i + 1]。如果它们相等,我们比较[i + i],a [i + 2]。如果没有,我们从数组中删除[i],[i + 1]。我们重复这个直到i> =(当前大小)/ 2。此时我们将'THE'元素占据第一个(当前大小)/ 2个位置。 这将保持不变性。

唯一需要注意的是,我们假设数组在链表中[因为它给出了O(n)复杂性。]

人们说什么?

-bhupi

答案 5 :(得分:0)

我的第一个想法(不够)将是:

  • 对阵列进行排序
  • 返回中间元素

但那将是O(n log n),就像任何递归解决方案一样。

如果您可以破坏性地修改数组(以及其他各种条件),您可以使用其计数或其他内容替换元素。你对阵列有什么了解吗?你可以修改它吗?

编辑留下我的答案给后人,但我认为Skeet得到了它。

答案 6 :(得分:0)

怎么样: 随机选择一小部分K元素并查找重复项(例如前4个,前8个等)。如果K == 4那么未获得至少2个重复项的概率是1/8。如果K == 8那么它会低于1%。如果您发现没有重复项,请重复此过程,直到您执行此操作。 (假设其他元素更随机分布,这将表现得非常差,例如,49%的数组=“A”,51%的数组=“B”)。

例如:

findDuplicateCandidate: 
    select a fixed size subset.
    return the most common element in that subset
    if there is no element with more than 1 occurrence repeat.
    if there is more than 1 element with more than 1 occurrence call findDuplicate and choose the element the 2 calls have in common    

这是一个常量顺序操作(如果数据集不错),那么按顺序(N)进行数组的线性扫描以进行验证。

答案 7 :(得分:0)

在php中 - 请检查它是否正确

function arrLeader( $A ){
$len = count($A);
$B = array();
$val=-1;
$counts = array_count_values(array); //return array with elements as keys and occurrences of each element as values
for($i=0;$i<$len;$i++){
    $val = $A[$i];
    if(in_array($val,$B,true)){//to avoid looping again and again
    }else{
     if($counts[$val]>$len/2){
      return $val;
     }
     array_push($B, $val);//to avoid looping again and again
    }
 }
 return -1;
}

答案 8 :(得分:-1)

int n = A.Length;
            int[] L = new int[n + 1];
            L[0] = -1;
            for (int i = 0; i < n; i++)
            {
                L[i + 1] = A[i];
            }
            int count = 0;
            int pos = (n + 1) / 2;
            int candidate = L[pos];
            for (int i = 1; i <= n; i++)
            {
                if (L[i] == candidate && L[pos++] == candidate)
                    return candidate;
            }
            if (count > pos)
                return candidate;
            return (-1);