Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding the Mode of Integers in an Array

Tags:

java

arrays

mode

For this problem, I am to write a method called mode that returns the most frequently occurring element of an array of integers. Assume that the array has at least one element and that every element in the array has a value between 0 and 100 inclusive. Break ties by choosing the lower value.

For example, if the array passed contains the values {27, 15, 15, 11, 27}, your method should return 15. (Hint: You may wish to look at the Tally program from earlier in this chapter to get an idea of how to solve this problem.)

I am having a problem seeing what is going wrong for a specific input. For instance:

mode({27, 15, 15, 27, 11, 11, 11, 14, 15, 15, 16, 19, 99, 100, 0, 27}) returns 15 which is correct, but mode({1, 1, 2, 3, 3}) returns 3 when it should be 1.

Here is the code:

public static int mode(int[] input) {
    int returnVal = input[0]; // stores element to be returned
    int repeatCount = 0; // counts the record number of repeats
    int prevRepCnt = 0; // temporary count for repeats

    for (int i=0; i<input.length; i++) { // goes through each elem

        for (int j=i; j<input.length; j++) { // compares to each elem after the first elem

            if (i != j && input[i] == input[j]) { // if matching values
                repeatCount++; // gets the repeat count

                if (repeatCount>=prevRepCnt) { // a higher count of repeats than before
                    returnVal=input[i]; // return that element
                }
                prevRepCnt = repeatCount; // Keeps the highest repeat record
            }
            repeatCount=0; // resets repeat Count for next comparison
        }
    }
    return returnVal;
}
like image 238
Jack L. Avatar asked May 30 '14 03:05

Jack L.


4 Answers

Here's a simpler way to solve this problem. Create an array called count of size 101. The indexes (0-100) represent the numbers you are counting. Traverse the input array and count the occurrences of each number. Finally, compare the counts to find the one that appears the most (tie goes to the lower number):

public static int mode(int[] input) {

    int[] count = new int[101];

    //count the occurrences
    for (int i=0; i < input.length; i++) {
        count[input[i]]++;
    }

    //go backwards and find the count with the most occurrences
    int index = count.length-1;
    for (int i=count.length-2; i >=0; i--) {
        if (count[i] >= count[index])
            index = i;
    }

    return index;
}
like image 146
Edwin Torres Avatar answered Nov 14 '22 22:11

Edwin Torres


I have recently analyzed four ways to calculate mode of the array:

  • If range of numbers in the array is small then use counting sort - O(N) time, (N) space but very efficient. This solution is directly applicable to the problem you are asking about, since you have only 101 possible values in the array.
  • Index elements in the array in hash table - O(N) time, O(N) space. This solution is applicable if values are taken from a large range, such as all integer numbers.
  • Sort the array and then count successive equal elements - O(NlogN) time, O(1) space. This solution is applicable if array is too large to build an index.
  • Partially sort the array but skip partitions smaller than current candidate - O(NlogN) time, O(1) space but much more efficient than fully sorting the array because many partitions will be skipped.

You can find source code (although in C#) for all four methods and performance comparison in this article: Finding Mode of an Array

like image 43
Zoran Horvat Avatar answered Nov 14 '22 21:11

Zoran Horvat


I would declare another variable to keep track of the "lower value". And check if the input[i] value is smaller than the lowerValue variable when it has the same count. Note I separated the > & = for your condition.

int lowerValue;

public static int mode(int[] input) {
    int returnVal = input[0]; // stores element to be returned
    int repeatCount = 0; // counts the record number of repeats
    int prevRepCnt = 0; // temporary count for repeats
    int lowerValue = Integer.MAX_VALUE; // initalize it with the highest integer value - 2147483647

    for (int i=0; i<input.length; i++) { // goes through each elem

        for (int j=i; j<input.length; j++) { // compares to each elem after the first elem

            if (i != j && input[i] == input[j]) { // if matching values
                repeatCount++; // gets the repeat count

                if (repeatCount>prevRepCnt) { // a higher count of repeats than before
                    returnVal=input[i]; // return that element
                    lowerValue = returnVal; // set the variable lowerValue to be the lower value
                }
                else if (repeatCount == prevRepCnt) && (input[i] < lowerValue) { // if it's the same number of count, take in whichever number is lower
                    returnVal=input[i]; // return that element
                    lowerValue = returnVal; // set the variable lowerValue to be the lower value
                }
                prevRepCnt = repeatCount; // Keeps the highest repeat record
            }
            repeatCount=0; // resets repeat Count for next comparison
        }
    }
    return returnVal;
}
like image 26
Sky Avatar answered Nov 14 '22 22:11

Sky


Base on your code all you need to change is.

public static int mode(int[] input) {
    int returnVal = input[0]; // stores element to be returned
    int repeatCount = 0; // counts the record number of repeats
    int prevRepCnt = 0; // temporary count for repeats

for (int i=0; i<input.length; i++) { // goes through each elem

    for (int j=i; j<input.length; j++) { // compares to each elem after the first elem

        if (i != j && input[i] == input[j]) { // if matching values
            repeatCount++; // gets the repeat count

            if (repeatCount>=prevRepCnt) { // a higher count of repeats than before
                returnVal=input[i]; // return that element
            }
            prevRepCnt = repeatCount; // Keeps the highest repeat record
        }
        repeatCount=0; // resets repeat Count for next comparison
    }
}
return returnVal;
}

here is what you need to change.

if (repeatCount>prevRepCnt) { // a higher count of repeats than before
  • take out the equal sign and you should be good.
like image 45
EdNight Avatar answered Nov 14 '22 21:11

EdNight