如果有多种模式或没有模式,则从用户输入数组中查找模式

问题描述

我正在处理一个项目,该项目提示用户创建并用整数填充数组,然后显示该数组的均值、众数、中位数和标准差。它首先询问用户数组的大小,输入的数字将声明和初始化数组。然后程序会迭代几次,要求用户声明一个整数值,每个值都会存储到数组中,直到数组被填满。然后程序将打印数组的内容,以及均值、众数、中位数和标准差。

我的代码似乎满足所有这些要求。但是,我正在努力的一件事是模式。虽然它确实打印出数组中重复次数最多的数字,但它没有考虑具有相同重复次数的多个模式,也没有考虑如果没有模式会发生什么。

现在,如果两个数字各输入两次,则显示的模式是第一个重复多次的数字。例如,如果我有一个大小为 10 个整数的数组,并且我输入的整数为 1、2、2、3、3、4、5、6、7、8,它将打印出“2.0”作为模式打印“2.0”和“3.0”。如果没有模式,它只是输入最初输入的数字,而不是说“无”。

实现这一目标的最佳行动方案是什么?

这是我的代码

.fullScreenCover(isPresented: $ShowSecondView,content: SecondView(ShowSecondView: $ShowSecondView))

解决方法

首先是代码,然后是解释。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.stream.Collectors;

public class ArrayStatistics {
    public static void main(String[] args) {
        int total = 0;
        Scanner input = new Scanner(System.in);
        System.out.print("Enter the size of your array >> ");
        int size = input.nextInt();
        int[] myArray = new int[size];
        Map<Integer,Integer> frequencies = new HashMap<>();
        System.out.print("Enter the integer values >> ");
        for (int i = 0; i < size; i++) {
            myArray[i] = input.nextInt();
            if (frequencies.containsKey(myArray[i])) {
                int frequency = frequencies.get(myArray[i]);
                frequencies.put(myArray[i],frequency + 1);
            }
            else {
                frequencies.put(myArray[i],1);
            }
            total += myArray[i];
        }
        System.out.println("\nIntegers:");
        for (int i = 0; i < size; i++) {
            System.out.println(myArray[i]);
        }

        double mean = calculateMean(size,total);
        System.out.println("\nMean: " + mean);

        List<Integer> mode = calculateMode(frequencies);
        System.out.println("Mode: " + mode);

        double median = calculateMedian(myArray);
        System.out.println("Median: " + median);

        double stdDev = calculateSD(mean,total,size,myArray);
        System.out.format("Standard Deviation: %.6f",stdDev);
    }

    public static double calculateMean(int count,int total) {
        double mean = ((double) total) / count;
        return mean;
    }

    public static List<Integer> calculateMode(Map<Integer,Integer> frequencies) {
        Map<Integer,Integer> sorted = frequencies.entrySet()
                                                  .stream()
                                                  .sorted((e1,e2) -> e2.getValue() - e1.getValue())
                                                  .collect(Collectors.toMap(e -> e.getKey(),e -> e.getValue(),(i1,i2) -> i1,LinkedHashMap::new));
        Iterator<Integer> iterator = sorted.keySet().iterator();
        Integer first = iterator.next();
        Integer val = sorted.get(first);
        List<Integer> modes = new ArrayList<>();
        if (val > 1) {
            modes.add(first);
            while (iterator.hasNext()) {
                Integer next = iterator.next();
                Integer nextVal = sorted.get(next);
                if (nextVal.equals(val)) {
                    modes.add(next);
                }
                else {
                    break;
                }
            }
        }
        return modes;
    }

    public static double calculateMedian(int myArray[]) {
        Arrays.sort(myArray);

        int val = myArray.length / 2;
        double median = ((myArray[val] + myArray[val - 1]) / 2.0);

        return median;
    }

    public static double calculateSD(double mean,int sum,int length,int[] myArray) {
        double standardDeviation = 0.0;
        for (double num : myArray) {
            standardDeviation += Math.pow(num - mean,2);
        }
        return Math.sqrt(standardDeviation / length);
    }
}

为了确定模式,您需要跟踪输入到数组中的整数的出现次数。我使用 Map 来做到这一点。我还在输入整数时计算总数。我在需要它的方法中使用这个总数,例如 calculateMean。每次需要时重新计算总数似乎是额外的工作。

您正在处理整数,那么为什么将 myArray 声明为 double 的数组?因此我将其更改为 int 数组。

您的问题是如何确定模式。因此我重构了方法 calculatMode。为了确定模式,您需要询问频率,因此是方法参数。由于您声称可以有零种、一种或多种模式,因此该方法返回 List。首先,我根据值对 Map 条目进行排序,即特定整数在 myArray 中的出现次数。我按降序对条目进行排序。然后我将所有已排序的条目收集到 LinkedHashMap 中,因为这是一个按照添加顺序存储其条目的映射。因此,LinkedHashMap 中的第一个条目将是出现次数最多的整数。如果第一个映射条目的出现次数为 1(一),则表示没有模式(根据我发现的此 definition):

如果列表中没有重复的数字,则列表没有模式。

在没有模式的情况下,方法 calculateMode 返回一个空的 List

如果第一个条目出现的次数超过一次,我会将整数添加到 List。然后我遍历剩余的地图条目并将整数添加到 List,如果它的出现次数等于第一个地图条目的出现次数。只要条目中出现的次数不等于第一个条目的次数,我就会退出 while 循环。现在 List 包含 myArray 中出现次数最多的所有整数。

这是一个示例运行(使用您问题中的示例数据):

Enter the size of your array >> 10
Enter the integer values >> 1 2 2 3 3 4 5 6 7 8

Integers:
1
2
2
3
3
4
5
6
7
8

Mean: 4.1
Mode: [2,3]
Median: 3.5
Standard Deviation: 2.211334