YUMI
YUMI

Reputation: 104

My Java method to find mode fails when my integer array is multimodal and when there's no mode

I am trying to write a java method to find the mode in an unsorted integer array. This works fine when there is only one mode within the array. But it gives out a random number when there's no mode in the array.

And also I need to make sure that my method addresses multimodal arrays as well. But I find difficulty in editing the code to return an array of modes.

public static int mode(int[] marksArray){

    int maxValue =0;int maxCount = 0;

    for (int i = 0; i < marksArray.length; ++i) {
        int count = 0;
        for (int j = 0; j < marksArray.length; ++j) {
            if (marksArray[j] == marksArray[i]) ++count;
        }
        if (count > maxCount) {
            maxCount = count;
            maxValue = marksArray[i];
        }
    }
    return maxValue;
}

Upvotes: 0

Views: 175

Answers (2)

RaffleBuffle
RaffleBuffle

Reputation: 5455

If there's more than one mode in the array then your code returns the first, which is not unreasonable.

To return all modes you need to maintain a list.

static List<Integer> mode(int[] array)
{
    List<Integer> mode = new ArrayList<>();

    int maxCount = 2;
    for(int i=0; i<array.length; i++)
    {               
        int count = 1;
        for(int j=i+1; j<array.length; j++)
            if(array[i] == array[j]) count++;

        if(count >= maxCount)
        {
            if(count > maxCount)
            {
                mode.clear();
                maxCount = count;
            }
            mode.add(array[i]);
        }
    }

    return mode;            
}

Note that there's no need to start the inner loop at 0. You can initialize count to 1 and start at i+1. Actually this is important as it means that the count for subsequent instances of array[i] will be less than the initial count, so they won't get added to the list as equal modes.

I've edited the code to detect the case where every element of the array is distinct, in which case there's no mode.

Upvotes: 2

Andreas
Andreas

Reputation: 159165

In Java 8+, it can be done like this:

public static int[] modes(int[] marksArray) {
    Entry<Long, List<Integer>> max = Arrays.stream(marksArray).boxed()
            .collect(groupingBy(identity(), TreeMap::new, counting())).entrySet().stream()
            .filter(e -> e.getValue() > 1)
            .collect(groupingBy(Entry::getValue, TreeMap::new, mapping(Entry::getKey, toList())))
            .lastEntry();
    return (max == null ? new int[0] : max.getValue().stream().mapToInt(Integer::intValue).toArray());
}

Test

public static void main(String[] args) {
    // Samples from https://www.mathsisfun.com/mode.html
    //          and https://www.purplemath.com/modules/meanmode.htm
    test(); // []
    test(1, 2, 4, 7); // []
    test(6, 3, 9, 6, 6, 5, 9, 3); // [6]
    test(1, 3, 3, 3, 4, 4, 6, 6, 6, 9); // [3, 6]
    test(13, 18, 13, 14, 13, 16, 14, 21, 13); // [13]
    test(8, 9, 10, 10, 10, 11, 11, 11, 12, 13); // [10, 11]
}
public static void test(int... marksArray) {
    System.out.println(Arrays.toString(modes(marksArray)));
}

Output

[]
[]
[6]
[3, 6]
[13]
[10, 11]

Upvotes: 1

Related Questions