平均数、中位数和众数

Mean, Median and Mode

您好,我的模态值代码有问题。这是我的代码:

public class basicStatistics {
 public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int n = in.nextInt();
    int[] arr = new int[n];
    int[] arrCount = new int[n];
    int maxCount = 0;
    double median = 0.0, mean = 0.0;
    for(int i = 0; i < n; i++) {
        arr[i] = in.nextInt();
        mean = mean + arr[i];
    }
    mean = mean/n;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++){
            if(arr[i] == arr[j]){
                arrCount[i]++;
            }
        if(maxCount < arrCount[i])
            maxCount = i;
        }
    }
    Arrays.sort(arr);
    if(n%2 == 0) {
        median = arr[n/2] + arr[n/2-1]; 
        median = median/2;
    } else {
        median = arr[n/2];
    }
    System.out.printf("%.1f\n", mean);
    System.out.printf("%.1f\n", median);
    System.out.println(arr[maxCount]);
 }
}

问题是当输入是这样时,我无法正确获取模态值:http://pastebin.com/HCqTrimY 我使用了 pastebin,因为它输入了 2500 个数字。我的代码为 Mode 输出数组值 259 而不是 2184 但是如果输入为 n = 10 并且数字 = 64630 11735 14216 99233 14470 4978 73429 38120 51135 67060 我得到正确的模式值或其他场景。

我还想利用 Java8 结构将代码转换为更高效的代码。先谢谢你了!

嗨,我回答了我自己的问题。答案是将数组排序放在获取 maxCount 的方法之上:

    ...
    mean = mean/n;
    Arrays.sort(arr);
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++){
            if(arr[i] == arr[j]){
                arrCount[i]++;
            }
        if(maxCount < arrCount[i])
            maxCount = i;
        }
    }
    if(n%2 == 0) { ...

现在唯一的问题是将其转换为 Java8 结构。编辑:当我尝试输入 n = 10 时出现了一个新问题;数字是 64630 11735 14216 99233 14470 4978 73429 38120 51135 67060 它没有正确获得模态值应该是 4978 它输出 11735.

编辑:为了修复新错误,我必须在评估 if(arr[i] == arr[j]) {...} 之前添加此代码 if(i != j) {...} .

"transform this to a Java8 structure" 是什么意思?使用像 mean += arr[i] 这样的增量也会更有效;而不是 mean = mean + arr[i];

针对您的问题:试试这个:

int maxCount = 0;
final int[] arrCount = new int[n];
for(int i = 0; i < n; i++) {
    for(int j = 0; j < n; j++){
        if(i != j && arr[i] == arr[j])
            arrCount[i]++;
    }
    if(maxCount < arrCount[i])
        maxCount = i;
}

如果你想使用 Java 8,你可以使代码更短。首先,mean:在这里,您可以从 int 数组 arr 创建一个 stream,然后只需调用 average 方法:

double mean = IntStream.of(arr).average().getAsDouble();

median 与您的代码几乎相同;我只是通过使用三元表达式 (... ? ... : ...) 而不是多行 if/else:

将它放在更少的行上
Arrays.sort(arr);
int len = arr.length;
double median = len % 2 == 0 ? (arr[len/2-1] + arr[len/2]) / 2. : arr[len/2];

mode 有点困难,最后但同样重要的是,因为您似乎需要最小模式,以防出现最频繁的多个数字。虽然您的双 for 循环方法也可以工作,但它具有二次复杂性,这可能成为更大数据集的问题。相反,您应该使用 Map 来计算不同的数字。在 Java 8 中,这可以使用 Collectors.groupingByCollectors.counting 轻松完成。然后,只需确定计数的 max,具有该计数的数字 filter,并获得其中的 min

Map<Integer, Long> counts = IntStream.of(arr).boxed()
        .collect(Collectors.groupingBy(x -> x, Collectors.counting()));
Long max = counts.values().stream().max(Comparator.naturalOrder()).get();
int mode = counts.entrySet().stream()
        .filter(e -> e.getValue().equals(max))
        .min(Comparator.comparing(Entry::getKey)).get().getKey();