Hi I'm having problem with my codes on the Modal value. Here is my code:
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]);
}
}
The issue is I can't get the Modal value right when the input is this: http://pastebin.com/HCqTrimY I used pastebin as it inputs 2500 numbers. My code outputs the array value 259 instead of 2184 for Mode however if the input is n = 10 and the numbers = 64630 11735 14216 99233 14470 4978 73429 38120 51135 67060 I get the mode value correct or for other scenario.
I also wanted to transform the code to a more efficient one utilizing the Java8 structure. Thank you in advanced!
If you want to use Java 8, you can make that code a lot shorter. First, the mean
: Here you can create a stream
from your int
-array arr
and then just call the average
method:
double mean = IntStream.of(arr).average().getAsDouble();
The median
is pretty much the same as in your code; I just put it on fewer lines by using a ternary expression (... ? ... : ...
) instead of a multi-line 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];
The mode
is a bit more difficult, last but not least since you seem to need the smallest mode in case there are multiple numbers appearing most often. While your double-for
-loop approach would work, too, it has quadratic complexity, which could become a problem for larger data sets. Instead, you should use a Map
to count the different numbers. In Java 8, this can be done very easily using Collectors.groupingBy
and Collectors.counting
. Then, just determine the max
of the counts, filter
the numbers that have that count, and get the min
of those.
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();