要求统计一个整型序列中出现次数最多的整数及其出现次数。
在一行中给出序列中整数个数N(0<N≤1000),依次给出N个整数,每个整数占一行。
在一行中输出出现次数最多的整数及其出现次数,数字间以空格分隔。题目保证这样的数字是唯一的。
在这里给出一组输入。例如:
10 3 2 -1 5 3 4 3 0 3 2在这里给出相应的输出。例如:
3 4分析:这里我并没用用到动态数组即ArrayList等类,这里只使用了一些数组去实现这个问题,也许这个代码写的非常暴力并且不美观,也不简洁,但是速度并不慢,而且可以完美解决问题,我会在之后的ArrayList类的用法分析中再现这个题目。先讲解我的方法。
我的方法简单来说就是通过多个映射来解决问题,首先我输入一些数据,得到的就是基本的数组,而我现在要通过这个数组来得到一些我想要的数据,即出现在这个数组里的每一个数的出现次数。首先我为这个数组里的每一个数都定义了一个标志位,标志位为0代表没有被访问过,为1代表被访问过,我这里被访问过就代表出现过了,再进行一轮新的计数时就不再访问它了,这里在代码中会详细说明,然后我还定义了一个结果表,结果表中有数据浪费,这是因为结果表对应原始表中某个数据第一次出现时的下标才会计数,这里也是一个映射,我可以通过这个映射找到某个数据出现的次数,也可以反过来找到那个数据,这里会有数据浪费,因为一个数据会出现多次,但时结果表只使用第一次出现时的那个位置,它其他出现的位置根据我的算法就会跳过不理睬。我这里会记录下最新出现的一个数的下标,它在结果表中是最后一个,下面是比较直观的解释:
原始数组
2
4
2
1
1
1
4
5
标志位表格
0
0
0
0
0
0
0
0
结果表
2
2
0
3
0
0
0
1
可以看到这三种数组的具体情况,在结果表中0就代表这个数字已经出现过不再处理而留下的空间浪费,而可以看到这三个表的有很强的映射关系,其中标志位表格与原始数组中的数据一一映射,代表每个数字是否出现过,而结果表中,原始数组中某个数第一次出现的下标,对应在结果表里,是它出现过的次数的下标,之所以这么做,是与算法有关系的。
拿这个举例子,首先我得到了一个数组,然后建立好了以上三个表,于是开始遍历原始数组了,首先第一个数据,是2,我查一下它的标志位是多少,发现是0,记下它的值然后向下进行,同时定义好一个记录它的个数的变量n,n先设为0,我用一个循环进行查找,遍历整个数组,只要发现是2,那么n就加一,同时标志位置为1,代表出现过,找完后,将这个n值给结果表中的2在原始数组中出现的第一个下标位置处,也就是当前的数组指针。
(这里发现,我这么做,是为了简便),然后进行下一个,发现是4,那么就重复上面的步骤,重复完后,指针到下一个,发现flag=1了,那么就不进行处理。如此循环即可。
代码流程:
import java.util.*; class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int number_list[] = new int[1000];//设置原始数组 int flag[] = new int[1000];//设置标志位 int number_list_jieguo[] = new int[1000];//设置结果表 int n,ls_number,jishuqi=0,max=0;//n为输入的个数,ls_number是记录一个数字出现次数的计数器,jishuqi则是记录最新的I的计数器,根据我的算法,最新的i就是结果表的最后一个下标,max用于找最大值 n = in.nextInt();//输入个数 for(int i = 0;i < n;i++) { number_list[i] = in.nextInt(); }//在进行输入数组,结果表和标志位不用初始化,在java中他们刚定义出来就是0 for(int i = 0; i < n; i++)//进行总的循环,I是数组指针 { if(flag[i] == 0)//如果发现标志位为0就会处理 { ls_number = 0;//出现次数计数器定为0 for(int j = 0; j < n;j++)//写一个暴力的循环,直接找到出现次数 { if(number_list[i] == number_list[j]) { flag[j]=1; ls_number+=1; //System.out.println(ls_number); } } number_list_jieguo[i] = ls_number;//放到结果表的i中,这里的I就是这个数第一次出现是的下标 //System.out.println(ls_number); } jishuqi = i;//记录最新的I,这个在if语句里边,只有新数字出现才进if语句,也就是说这个i是最新出现的新数字,因为是从前往后扫描,所以越新出现,下标越大,二最后出现的一个新数字就是结果表的末尾,这个其实是为了减少空间浪费 } //System.out.println(jishuqi); //System.out.println(Arrays.toString(number_list_jieguo)); max = 0;//然后是找最大值,比较简单 for(int i = 1;i <= jishuqi;i++) { if(number_list_jieguo[i] > number_list_jieguo[max]) max = i; } System.out.println(number_list[max]+" "+number_list_jieguo[max]); } } //这里在找次数时,在得到一个新数字后并没有急着处理,而是先设定计数器为0,并且仅仅记住我要找这个数字,而不是马上计数器就加一,设定好后再重新遍历,从0开始找,这是为了避免在查重时把自己也算进去。用的东西很低端,但是比较底层,当然使用ArrayList和HushMap能更好的解决问题,但是第一次解决问题时我还不会,所以以后会重现一次并且分享。