x称为一个长度为n的数组a的主元素,如果这个数组里面等于x的元素数目不少于n/2个。
例如,a={2,3,2,2,5,3,2,4,2}, x = 2就是主元素。给定包含n个元素的数组a,主元素问题就是判断数组a是否包含一个主元素x。
三方法实现:
方法一:求中位数,主元素肯定是中位数,否则该元素数量少于n/2则不是主元素:快速排序,然后确定中位数时间复杂度O(nlogn)
方法二:分治的思想:
若T 中存在主元素,则将T 分为两部分后,T 的主元素也必为两部分中至少一部分的主元素,因此可用分治法。将元素划分为两部分,递归地检查两部分有无主元素。算法如下:a. 若T 只含一个元素,则此元素就是主元素,返回此数。 b. 将T 分为两部分T1 和T2(二者元素个数相等或只差一个),分别递归调用此方法求其主元素m1 和m2。 c. 若m1 和m2 都存在且相等,则这个数就是T 的主元素,返回此数。d. 若m1 和m2 都存在且不等,则分别检查这两个数是否为T 的主元素,若有则返回此数,若无则返回空值。e. 若m1 和m2 只有一个存在,则检查这个数是否为T 的主元素,若是则返回此数,若否就返回空值。f. 若m1 和m2 都不存在,则T 无主元素,返回空值。方法三:思路比较新颖,原理是如果一个数组中存在一个主元素(个数大于n/2),则同时删除两个不相等的值,这个主元素不会改变。
简单的说就一个大小为n数组中存在一个元素的个数大于n/2,则如果用这个数组中其他元素和该主元素进行抵消的话,最后剩下的一定是主元素,因为主元素个数最多。
该方法可以在O(n)的时间内找到主元素,十分高效。
方法一代码如下:
1 #include <stdio.h> 2 3 //求中位数的方法 4 int swap(int *a, int *b) 5 { 6 int temp = 0; 7 temp = *a; 8 *a = *b; 9 *b = temp; 10 } 11 12 int partition(int *num, int start, int end) 13 { 14 int x = num[end]; 15 int i = start-1; 16 int j; 17 for (j = start; j < end; j++) { 18 if (num[j] <= x) { 19 i = i + 1; 20 swap(&num[i], &num[j]); 21 } 22 } 23 swap(&num[i+1], &num[end]); 24 return i+1; 25 26 } 27 28 void quicksort(int *num, int start, int end) 29 { 30 if( start < end) { 31 int mid = partition(num, start, end); 32 quicksort(num, start, mid-1); 33 quicksort(num, mid+1, end); 34 } 35 } 36 37 int main() 38 { 39 int i; 40 int num1[]={2,8,7,1,3,5,6,4}; 41 int num[] = {2,3,1,2,2,2,5,4,2,2}; 42 quicksort(num, 0, 7); 43 for (i = 0; i < 8; i++) { 44 printf("%d\n", num[i]); 45 } 46 int index = 9/2; //奇数n/2偶数n/2-1 47 if (num[0] == num[index] || num[9] == num[index]) { 48 printf("main element exits: index = %d element = %d\n", index, num[index]); 49 } 50 else { 51 printf("main element not exits\n"); 52 } 53 }
方法二代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 typedef struct _node{ 5 int data; 6 int count; 7 }*node; 8 9 int checkNum(int *num, int p, int q, int data) 10 { 11 int count = 0; 12 int i; 13 for (i = p-1; i < q; i++) { 14 if (num[i] == data) { 15 count++; 16 } 17 } 18 return count; 19 } 20 21 node checkAnotherPart(int *num, int len, int p, int q, node nodec) 22 { 23 nodec->count = checkNum(num, p, q, nodec->data) + nodec->count; 24 if (nodec->count >= len/2) { 25 return nodec; 26 } 27 else { 28 return NULL; 29 } 30 } 31 node checkMaster(int *num, int p, int q) 32 { 33 node nodetmp = malloc(sizeof(node)); 34 node nodea = malloc(sizeof(node)); 35 node nodeb = malloc(sizeof(node)); 36 if (p == q) { 37 nodetmp->data = num[p-1]; 38 nodetmp->count = 1; 39 return nodetmp; 40 } 41 int len = q - p + 1; 42 int mid = p + len / 2; 43 nodea = checkMaster(num, p, mid-1); 44 nodeb = checkMaster(num, mid, q); 45 if (nodea == NULL && nodeb == NULL) { 46 return NULL; 47 } 48 if (nodea == NULL && nodeb != NULL) { 49 return checkAnotherPart(num, len, p, mid-1, nodeb); 50 } 51 if (nodea != NULL && nodeb == NULL) { 52 return checkAnotherPart(num, len, mid, q, nodea); 53 } 54 if (nodea != NULL && nodeb != NULL) { 55 if (nodea->data == nodeb->data) { 56 nodea->count = nodea->count + nodeb->count; 57 return nodea; 58 } 59 else { 60 node nodec = checkAnotherPart(num, len, p, mid-1, nodeb); 61 if (nodec != NULL) { 62 return nodec; 63 } 64 else { 65 return checkAnotherPart(num, len, mid, q, nodea); 66 } 67 } 68 } 69 70 } 71 72 int main() 73 { 74 75 int num[] = {2,2,3,1,2,2,2,5,4,2,2}; 76 node masterNode = checkMaster(num, 1, 11); 77 printf("num = %d count = %d\n", masterNode->data, masterNode->count); 78 }
方法三代码如下:
1 #include <stdio.h> 2 3 int mainElement(int *num, int n) 4 { 5 int seed = num[0]; 6 int count = 1; 7 int i; 8 for (i = 1; i < n; i++) { 9 if (seed == num[i]) { 10 count++; 11 } 12 else { 13 if (count > 0) { 14 count--; 15 } 16 else { 17 seed = num[i]; 18 } 19 } 20 21 } 22 count = 0; 23 for (i = 0; i < n; i++) { 24 if (num[i] == seed) { 25 count++; 26 } 27 } 28 if (count >= n/2) { 29 return seed; 30 } 31 return 0; 32 } 33 34 int main() 35 { 36 int num1[]={2,8,7,1,3,5,6,4}; 37 int num[] = {2,3,1,2,2,2,5,4,2,2}; 38 int mainElem = mainElement(num, 8); 39 if (mainElem != 0) 40 printf("main element is %d\n", mainElem); 41 else 42 printf("main element not exits\n"); 43 44 }