1 票选优秀员工
1.1 问题描述
(1) 问题描述:五一节,何老板的公司票选优秀员工。何老板的公司共有m 个候选员工,编号1 到m。共有n 个员工参与了投票,每人只能投一票,得票过半(票数>n/2)的员工将获得优秀员工奖,何老板请你快速找出这个员工的编号。
(2) 输入格式:第一行,一个整数n;接下来一行,n 个空格间隔的整数,表示每个员工投票的编号
(3) 输出格式:一行,一个整数,表示当选优秀员工的编号。(数据保证一定有解)
(4) 样例输入:
7
8 1 8 2 8 9 8
样例输出:
8
(5) 提示:对于30%的数据,有m<=1,000,n<=1,000;对于100%的数据,有m<=1,000,000,000,n<=1,000,000;注意:此题空间限制为0.5m
(6) 基本要求:编程语言不限,提交技术报告(包括算法描述、算法的时间复杂度与空间复杂度分析、源代码、实验结果与分析)
1.2 编程实现
1.2.1 算法思想
(1)算法1:
首先想到的就是暴力解法,将每个员工的投票编号存入数组中,然后进行排序,由于是票数过半的员工获奖,那么排完序直接输出中间的数组元素即可。
算法1代码如下:
import java.util.*;
public class Vote1 {
public static void main(String [] args) {
Scanner sc = new Scanner(System.in);
int n =sc.nextInt();
int [] a = new int[n+1];
for(int i=1;i<n+1;i++) {
a[i]=sc.nextInt();
}
Arrays.sort(a);
System.out.println(a[n/2+1]);
sc.close();
}
}
但是该算法需要用到排序,排序时间复杂度一般是O(nlog2n),时间复杂度较高。下面介绍一种时间复杂度为O(n)的算法。
(2)算法2:
首先定义一个计数器变量count和保存最多元素的变量major,均初始化为0。然后:
①首先将数组的第一个元素赋给major,count赋值1;
②然后遍历数组其他元素,如果major和当前数组元素值相同,则count++;
③反之,若count==0,则将major赋值为数组的当前元素;反之,count–;
④重复上述两步,直到扫描完数组;
⑤count赋值为0,再次从头扫描数组,如果数组元素值与major的值相同则count++,直到扫描完数组为止;
⑥如果此时count的值大于n/2,则输出major的值。
算法2代码如下:
import java.util.*;
public class Vote2 {
public static void main(String [] args) {
Scanner sc = new Scanner(System.in);
int n =sc.nextInt();
int [] array = new int[n];
int count = 0;
int major = 0;
int temp_count = 0;
for(int i=0;i<n;i++) {
array[i] = sc.nextInt();
if(i==0) {
major = array[0];
count = 1;
}else if(major == array[i]) {
count++;
}else if(count == 0) {
major = array[i];
}else {
count--;
}
}
for(int j=0;j<n;j++) {
if(major == array[j])
temp_count++;
}
if(temp_count > n/2)
System.out.println(major);
sc.close();
}
}
此时算法2中避免了数组排序问题,从而降低了时间复杂度。算法2中使用了两次n次循环,因此时间复杂度为O(n),另外使用了一个长度为n的一维数组,因此空间复杂度为O(n)。
1.2.2 实验结果
(1)算法2测试样例1:
7
8 1 8 2 8 9 8
测试结果如图1所示:
(2)算法2测试样例2:
14
5 5 4 7 5 6 5 10 5 18 5 5 5 7
测试结果如图2所示: