问题描述
给定n个正整数,找出它们中出现次数最多的数。如果这样的数有多个,请输出其中最小的一个。
输入格式
输入的第一行只有一个正整数n(1 ≤ n ≤ 1000),表示数字的个数。
输入的第二行有n个整数s1, s2, …, sn (1 ≤ si ≤ 10000, 1 ≤ i ≤ n)。相邻的数用空格分隔。
输出格式
输出这n个次数中出现次数最多的数。如果这样的数有多个,输出其中最小的一个。
样例输入
6
10 1 10 20 30 20
样例输出
10
CCF官网给出的源码:
import java.util.*; public class Main { public static void main(String[] args) { new Main().run(); } public void run() { Scanner fin = new Scanner(System.in); int N = fin.nextInt(); //输入数字个数 int[] count = new int[10001];//这里设数组大小为10001是防止输入的数超过数组的下标值 for (int i = 0; i < N; ++i) { //对于数组count,下标i代表每个数,count[i]代表i出现的次数 //数组只开辟了空间不赋值的默认值为0,若数字10只出现2次,则count[10]=2 ++count[fin.nextInt()]; } int maxCount = -1; int result = 0; for (int i = 1; i <= 10000; ++i) { //i从1开始增大,满足“出现次数最多的数有多个,输出其中最小的一个”条件 if (count[i] > maxCount) { maxCount = count[i]; result = i; } } System.out.println(result); } }
这种解法简单但耗费时间和资源,同时也不好想,涉及到数值和次数两个记录值,相信多数人会想到用可以保存键值对的HashMap解决,下面给出这种常规解法:
import java.util.*; public class Main{ public static void main(String args[]){ Scanner scanner = new Scanner(System.in); int N = Scanner.nextInt(); int arr[] = new int[N]; for(int i=0;i<N;i++){ arr[i] = scanner.nextInt(); } Map<Integer,Integer> map = new HashMap<Integer,Integer>(); for(int i=0;i<arr.length;i++){ if(map.containsKey(arr[i])){ map.put(arr[i],map.get(arr[i])+1); }else{ map.put(arr[i],1); } } List<Map.Entry<Integer,Integer>> list = new ArrayList<Map.Entry<Integer,Integer>>(map.entrySet()); Collections.sort(list,new Comparator<Map.Entry<Integer,Integer>>(){ //需要重写compare()方法(默认升序),改成按value降序 public int compare(Map.Entry<Integer,Integer> o1,Map.Entry<Integer,Integer> o2){ return(o2.getValue()-o1.getValue());//返回值为正,则将2个对象对调 } }); System.out.println(list.get(0).getKey()); //获取出现次数最多的那个数 } }
Collections.sort()方法中的参数Comparator是比较器,它本身只负责比较两个数据,然后把结果返回,至于它的调用者获的返回结果后如何处理它不管,也就是说Comparator本身不负责排序,只负责比较,排序处理是它的调用者实现的,也就是在sort方法里实现的。