题目描述
题目分析
因为主元素的定义为大于n/2,那么被遍历到的次数一定是大于n/2,故可把遍历到主元素作为+1,遍历到非主元素作为-1,若主元素存在,则最后相加的结果一定是大于0。若不存在,则相加后一定小于或等于0。
由此我们可以根据主元素这一边界特征进行判断。
解法
从前向后扫描数组元素,标记一个可能成为主元素的元素Num。然后重新计数,确认Num是否为主元素。
Step 1:选数组中第一个元素为“”假设”主元素,将第一个遇到的整数A[0]保存到c中,记录Num的出现次数为1;若遇到的下一个整数仍等于A[0],则计数加1,否则计数减1;当计数减到0时,将遇到的下一个整数(A[i])保存到c中,计数重新记为1,开始新一轮计数,则从当前位置开始重复上述过程,直到扫描完全全部数组元素。
Step 2:判断c中元素是否是真正的元素。再次扫描该数组,统计c中元素出现的次数,若大于n/2,则为主元素;否则,序列中不存在主元素。
int findMain(int A[], int n){
int c, count = 1; // 使用c存储候选主元素,count来计数
c = A[0];
for(i = 1; i < n; i++){
if(A[i] == c){
count++;
}else{
if(count > 0)
count--;
else{
c = A[i];
count = 1;
}
}
}
if(count > 0){
for(i = count = 0; i < n; i++){ // 统计候选主元素的实际出现次数
if(A[i] == c)
count++;
}
if(count > n/2) return c;
}
return -1; // 不存在候选主元素
}
时间复杂度为O(n),空间复杂度为O(1)