1.众数问题:
给定含有N个元素的多重集合S,每个元素在S中出现的次数称为该元素的重数,多重集合S中重数最大的元素称为多重集合S的众数,众数的重数称为多重集合S的重数,试求一个给定多重结合的重数和众数。
例如:S={a,b,b,b,f,f,4,5}的重数是3,众数是b
2.算法思路:
- 首先为集合S排序,使之成为有序的数组(使用Arrays类的sort方法)
- 取中位数为众数,中位数的个数为重数,确定左右界
- 向左界递归,取中位数为众数,取中位数个数为重数,比较
- 向右界递归,取中位数为众数,取中位数个数为重数,比较
3.问题:
翻阅网上的代码,多是使用c++实现,而c++代码中有引用参数传递的过程,在程序运行中可以直接引用函数传参,但Java中没有提供。在阅读(7条消息) 分治法-众数问题java实现_cook_1996的博客-CSDN博客 这篇博客后,发现了IntHolder这个类。
IntHolder持有者类型:因为java中只存在值传递,同时包装类一旦创建其数值是不能改变的。所有不可能实现一个方法改变一个数据类型的值。如果想编写一个修改数据值参数的方法,就需要使用在 org.omg.CORBA 包中定义的持有者(holder)类型,包括IntHolder、BooleanHolder等。每个持有者类型都包含一个共有域值,通过它可以访问储存在其中的值。
4.代码:
import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Scanner;
public class Mode {
public static void getMaxCnt(int a[], int n, IntHolder num, IntHolder maxCnt){
int l =0, r = 0;
int s;
int mid = n / 2;
for( l = 0;l < mid;l ++){
if(a[l] == a[mid])
break;
}
for(r = mid + 1;r < n;r ++){
if(a[r] != a[mid])
break;
}
s = r - l;
if(s > maxCnt.value){
num.value = a[mid];
maxCnt.value = s;
}
if(s == maxCnt.value){
if(num.value > a[mid]){
num.value = a[mid];
maxCnt.value = s;
}
}
if(l + 1 > maxCnt.value){
getMaxCnt(a,l+1,num,maxCnt);
}
if(n - r > maxCnt.value){
int [] b = new int[n-r];
for(int i = 0;i < n-r;i ++){
b[i] = a[r + i];
}
getMaxCnt(b,n-r,num,maxCnt);
}
}
public static void main(String[] args) {
int i,n;
IntHolder num = new IntHolder();
IntHolder maxCnt = new IntHolder();
System.out.println("请输入数组个数:");
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
int []a = new int[n];
System.out.println("请输入一个数组:");
for(i = 0;i < n;i ++){
a[i] = scanner.nextInt();
}
Arrays.sort(a);
getMaxCnt(a,n,num,maxCnt);
System.out.println("众数:" + num.value + " 重数:" + maxCnt.value);
}
}