分治算法—work2_2_23—找主元(只能用“=”进行判断)

题目:

 

算法思想: 
对于整个数组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”

原文链接:加载失败,请重新获取