在数组中寻找主要元素的算法。
这个是数据结构与算法分析-C语言描述一书的课后习题2.19的解答。
长度为n的数组A的主要元素,指的是在所有元素中出现次数超过n/2次的元素。(所以最多有一个而已。)下面的算法是Google出来的答案(原来是伪代码,我用C#实现了),教材上给的提示实在是难于理解。
//
Let T [1..n] be an array of n integers. An integer is a majority element in T if it appears
// strictly more than n/2 times in T. This paper is concerned with finding an algorithm that
// can decide whether an array T [1..n] contains a majority element, and if so, find it. The
// algorithm runs in linear time in the worst case.
// Also, the only comparisons allowed between the elements of T are tests of equality. This
// means, there does not exist an order relation between the elements of the array.
// Input : An input array, unsorted, of the type T [i..j].
// Output : The majority element ele, if it exists. If a majority element does not exist, the algorithm returns a null.
public static Object FindMajority(Int32[] Input)
{
Int32 candidate = FindElement(Input);
Int32 count = 0;
for(Int32 i = 0; i < Input.Length; i++)
if (Input[i] == candidate) count++;
if (count > Input.Length / 2) return candidate;
else return null;
}
private static Int32 FindElement(Int32[] A)
{
Int32 m = 0; // marker
Int32 ele = 0;
for (Int32 x = 0; x < A.Length; x++)
{
if (m == 0)
{
m = 1;
ele = A[x];
}
else if (A[x] == ele) m++;
else m--;
}
return ele; // The candidate
}
// strictly more than n/2 times in T. This paper is concerned with finding an algorithm that
// can decide whether an array T [1..n] contains a majority element, and if so, find it. The
// algorithm runs in linear time in the worst case.
// Also, the only comparisons allowed between the elements of T are tests of equality. This
// means, there does not exist an order relation between the elements of the array.
// Input : An input array, unsorted, of the type T [i..j].
// Output : The majority element ele, if it exists. If a majority element does not exist, the algorithm returns a null.
public static Object FindMajority(Int32[] Input)
{
Int32 candidate = FindElement(Input);
Int32 count = 0;
for(Int32 i = 0; i < Input.Length; i++)
if (Input[i] == candidate) count++;
if (count > Input.Length / 2) return candidate;
else return null;
}
private static Int32 FindElement(Int32[] A)
{
Int32 m = 0; // marker
Int32 ele = 0;
for (Int32 x = 0; x < A.Length; x++)
{
if (m == 0)
{
m = 1;
ele = A[x];
}
else if (A[x] == ele) m++;
else m--;
}
return ele; // The candidate
}
从直接上很容易感觉这个算法是正确的,证明的大致思路就是如果一个元素符合条件,那么最后返回的值就一定是它。因为它的权值是最大的,如果没有元素符合条件,那么就不会通过 FindMajority中的测试。
这个算法的复杂度明显为O(n)