平均数、中位数和众数
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.groupingBy
和 Collectors.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();
您好,我的模态值代码有问题。这是我的代码:
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.groupingBy
和 Collectors.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();