题目:
算法思想:
对于整个数组A,将其分成长度相差为1的两部分A1和A2
1、如果A1中没有主元素,且A2中没有主元素,则A中没有主元素
2、如果A1中有主元素,A2中没有主元素,将A1中的主元素拿到A2中去比对, 如果比对得到A1中主元素在A1、A2中的出现的次数大于数组A长度的1/2,那A1的主元素就是A的主元素
3、如果A2中有主元素,A1中没有主元素,与情况2相似处理
4、如果A1、A2 都有主元素,又有四种情况,如果A1主元素==A2主元素,得到A的主元素,否则将A1主元素拿到A2中去比对,如果它不是A的主元素,再将A2的主元素拿到A1中去比对,如果比对不成功说明A没有主元素。
const int Inf = 0x7fffffff;
struct Node //存储主元素
{
int ele;
int num;
};
Node* findmain(int a[], int l, int r, int len, int e, int cou) //比对
{
int nnum = 0;
int i;
for (i = l; i <= r; i++)
{
if (a[i] == e)
{
nnum++;
}
}
if (cou + nnum > len / 2)
{
Node * n = new Node;
n->ele = e;
n->num = nnum + cou;
return n;
}
return NULL;
}
Node* findallmain(int a[], int l, int r) //划分->递归->合并(问题处理)
{
if (l == r)
{
Node * node = new Node;
node->ele = a[l];
node->num = 1;
return node;
}
int len = r - l + 1;
int m = l + len / 2;
Node *lmain = findallmain(a, l, m - 1); //A1主元素
Node *rmain = findallmain(a, m, r); //A2主元素
if (lmain == NULL && rmain == NULL) //A1、A2 中都没有主元素
{
return NULL;
}
if (lmain == NULL && rmain != NULL) //A2中有主元素,A1中没有主元素,将A2中的主元素拿到A1中去比对
{
return findmain(a, l, m - 1, len, rmain->ele, rmain->num);
}
if (lmain != NULL && rmain == NULL) //A1中有主元素,A2中没有主元素, 将A1中的主元素拿到A2中去比对
{
return findmain(a, m, r, len, lmain->ele, lmain->num);
}
if (lmain != NULL && rmain != NULL) //A1中有主元素,A2中有主元素
{
if (rmain->ele == lmain->ele) //A1、A2主元素相等
{
Node * n = new Node;
n->ele = lmain->ele;
n->num = lmain->num + rmain->num;
return n;
}
else
{
Node *amain = findmain(a, l, m - 1, len, rmain->ele, rmain->num); //将A2中的主元素拿到A1中去比对
if (amain != NULL)
{
return amain;
}
return findmain(a, m, r, len, lmain->ele, lmain->num); //将A2中的主元素拿到A1中去比对
}
}
return NULL;
}
int main()
{
int a[] = {1, 1, 2, 3 ,4 ,5 , 6, 2, 2 ,2, 2, 2, 2};
Node *node = findallmain(a, 0, 12);
if (node == NULL) //查找失败
{
cout << "can't find the main element!" << endl;
}
else
{
cout << "elem: " << node->ele << " num: " << node->num << endl;
}
return 0;
}
(a) O(nlogn) 算法
基本思路:类似于归并排序的递归方法。如果将数组A分成两个长度(接近)相等的两个子序列A1和A2,则如果数组A中存在主元素,则A1或A2中也一定存在一个主元素。这样在对两个子序列进行合并的merge算法中,不需要进行排序,而是要分别检查A1或A2可能存在的主元素能否与另一个子序列(A2或A1)中的元素构成整个数组A中的主元素。由于这个merge算法一定可以在O(n)时间内完成,故整个算法的复杂度为O(nlogn)。
算法基本描述如下:
majority (A[1 . . . n])
if n = =1 return A[1]
let AL,AR be the first and second halves of A
ML = majority(AL) and MR = majority(AR)
if neither half has a majority
return “no majority”
else
check whether either ML or MR is a majority element of A
if so, return that element
else return “no majority”