题目来源: 计算机考研408真题2013年41题
题目描述:
- 描述: 41.(13分)已知一个整数序列A=(),其中。若存在则称x为A的主元素。例如A=(0,5,5,3,5,7,5,5),则5为主元素:又如A=(0,5,5,3,5,1,5,7),则A中没有主元素。假设A中的n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出A的主元素。若存在主元素,则输出该元素;否则输出-1。要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C、C++或Java语言描述算法,关键之处给出注释。
3)说明你所设计算法的时间复杂度和空间复杂度。
思路1:
-
从前向后扫描数组元素,标记出一个可能成为主元素的元素element。然后重新计数,确认element是否是主元素。
- 1.依次扫描所给数组中的每个整数,将第一个遇到的整数number保存到element中,记录出现次数count为1;
- 2.若遇到的下一个整数仍等于number,则计数加1,否则计数减1;
- 3.当计数减到0时,将遇到的下一个整数保存到element中,计数count重新记为1,开始新一轮计数,即从当前位置开始重复上述过程,直到扫描完全部数组元素。
- 4.判断element是否是真正的主元素:再次扫描该数组,统计element在数组中出现的次数,若大于n/2,则为主元素;否则,序列中不存在主元素。
-
助解: 可以将数组分为主元素与非主元素两个阵营,而计数的count的加加减减可以理解为主元素与非主元素的一一抵消,而主元素的个数是大于一半的,所以抵消到最后,剩下的一定是主元素,即count>0
具体实现:
public class day408_13 {
static int Search_element(int arr[],int n){
int element = arr[0],count = 1; //element用来保存主元素,将第一个遇到的整数arr[0]为主元素
//count用来计数
for(int i = 1;i < n;i ++){ //查找候选主元素
if(arr[i] == element){
count ++; //对arr中的主元素计数
}else if(count > 0){
count --; //处理不是候选主元素的情况(理解为主元素与非主元素抵消)
}else{ //当计数减到0时
element = arr[i]; //更换主元素,重新计数
count = 1;
}
}
if(count > 0){
count = 0; //将count归零,开始统计上面找到的主元素在数组中的个数
for (int i = 0; i < n; i++) { //统计候选主元素的实际出现次数
if(arr[i] == element){
count ++;
}
}
}
if(count > n/2){
return element; //确认候选主元素
}else{
return -1; //不存在主元素
}
}
public static void main(String[] args) { //测试
int[] arr = {0,5,5,7,5,5,5,6,7,1};
System.out.println(Search_element(arr,10));
}
}
- 复杂度分析:
- 时间复杂度O(n):对数组进行遍历
- 空间复杂度O(1):常数的空间。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 21 天,点击查看活动详情”