给定n个整数数组,其中一个元素出现的次数超过n / 2次。我们需要在线性时间和恒定的额外空间中找到该元素。
YAAQ:又一个阵列问题。
答案 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);