主元素问题

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 }

 

posted on 2013-03-10 14:42  愤怒的屎壳螂  阅读(435)  评论(0编辑  收藏  举报

导航