题目描述:
已知一个整数序列A={a0,a1,a2,...an-1} 其中0<=ai<n(0<=i<n).若存在 ap1=ap2=...=apm=x且m>n/2(0<=pk<n,1<=k<=m),则称x为A的主元素。如 A={0,5,5,3,5,7,5,5},则5为主元素,又如A={0,5,5,3,5,1,5,7},则A中没有 主元素,若有主元素输出该元素,否则输出-1.分析:因为有这个条件0<=ai<n(0<=i<n),我们可以自然而然的想到开辟一个n个长度的数组,用下标来代替0,1,2...n-1的值,数组里面自然就是存储其出现的次数咯,然后判断其个数即可,代码如下:
#include#define N 8int A[N];int main() { for(int i=0;i N/2) { ok = 0; printf("%d\n",i); break; } } if(ok) printf("-1\n"); return 0;}
当然这种思路的时间复杂度为O(n),空间复杂度为O(n),能有更好的办法吗,将空间复杂度将为O(1)呢?在王道上看到这样一种思想,就是用一个count来记录num,如果下次出现的还是num,则count加一,否则减一,若为主元素,则在抵消的过程中它的count最终是大于0,而不是主元素的话在抵消的过程中会变为0。具体算法描述:
- 选取候选的主元素:依次扫描所给数组中的每个整数,将第一个遇到的整数num保存到c中,而用计算器count来保存出现的次数,下次再出现num则计数器加1,否则计数器减1;当计数器减到0,遇到下一个整数保存在c中,计数器重新记数为1,开始新一轮计数,即从当前位置开始重复上述过程,直到扫描完全部的数组元素。
- 判断c中是否是正真的主元素:再次扫描数组,统计c在数组中出现的次数是否大于n/2,大于则为中元素否则序列不存在主元素。
void Majority(int A[],int n){ int i,c,count=1; c = A[0]; for(i=1;i0) count--; else { c = A[i]; count = 1; } } } if(count>0){ count = 0; for(i=0;i n/2) printf("%d\n",c); else printf("-1\n");}
实现程序的时间复杂度为O(n),空间复杂度为O(1).