Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Counting occurrences of integers in an array [duplicate]

I'm writing a program that counts the occurrences of integers entered into an array, eg if you entered 1 1 1 1 2 1 3 5 2 3, the program would print out the distinct numbers followed by their occurrences, like this:

1 occurs 5 times, 2 occurs 2 times, 3 occurs 2 times, 5 occurs 1 time

And it's almost finished, aside from one problem I can't figure out:

import java.util.Scanner;
import java.util.Arrays;
public class CountOccurrences
{
   public static void main (String [] args)
   { 

    Scanner scan = new Scanner (System.in);

    final int MAX_NUM = 10;  

    final int MAX_VALUE = 100;

    int [] numList;

    int num;

    int numCount;

    int [] occurrences; 

    int count[];

    String end;

    numList = new int [MAX_NUM];

    occurrences = new int [MAX_NUM];

    count = new int [MAX_NUM];

 do
  {
     System.out.print ("Enter 10 integers between 1 and 100: ");

     for (num = 0; num < MAX_NUM; num++)
     {
        numList[num] = scan.nextInt();
     }

     Arrays.sort(numList);

     count = occurrences (numList); 

     System.out.println();   

     for (num = 0; num < MAX_NUM; num++)
     {
        if (num == 0)
        {
           if (count[num] <= 1)
              System.out.println (numList[num] + " occurs " + count[num] + " time");

           if (count[num] > 1)
              System.out.println (numList[num] + " occurs " + count[num] + " times");
        } 

        if (num > 0 && numList[num] != numList[num - 1])
        {
           if (count[num] <= 1)
              System.out.println (numList[num] + " occurs " + count[num] + " time");

           if (count[num] > 1)
              System.out.println (numList[num] + " occurs " + count[num] + " times");
        }   
     }          

     System.out.print ("\nContinue? <y/n> ");
     end = scan.next(); 

  } while (!end.equalsIgnoreCase("n"));
}


 public static int [] occurrences (int [] list)
 {
      final int MAX_VALUE = 100;

      int num;

      int [] countNum = new int [MAX_VALUE];

      int [] counts = new int [MAX_VALUE];

      for (num = 0; num < list.length; num++)
  {
     counts[num] = countNum[list[num]] += 1;
  }

  return counts;
 } 
}

The problem I'm having is that no matter what the current value for 'num' is, 'count' only prints out 1, and the problem isn't in the method that counts the occurrences, because when you enter numbers in the place of the variable, the value changes.

Is there any way that I can alter this so that it'll print out the occurrences properly, or should I try something else? And the simpler the solution, the better, as I haven't yet gone past single dimension arrays.

Thanks for the help!

like image 870
Len Avatar asked Nov 01 '15 04:11

Len


3 Answers

Try HashMap. For this type of problem hashes is very efficient and fast.

I write this function which take array and return a HashMap whose key is the number and value is the occurance of that number.

public static HashMap<Integer, Integer> getRepetitions(int[] testCases) {    
    HashMap<Integer, Integer> numberAppearance = new HashMap<Integer, Integer>();

    for(int n: testCases) {
        if(numberAppearance.containsKey(n)) {
            int counter = numberAppearance.get(n);
            counter = counter+1;
            numberAppearance.put(n, counter);
        } else {
            numberAppearance.put(n, 1);
        }
    }
    return numberAppearance;
}

Now iterate throught hashmap and print occurance of numbers like this :

HashMap<Integer, Integer> table = getRepetitions(testCases);

for (int key: table.keySet()) {
        System.out.println(key + " occur " + table.get(key) + " times");
}

Output:

enter image description here

like image 162
Irfan Avatar answered Oct 24 '22 16:10

Irfan


I'd use a Bag, a collection that counts the number of times an item appears in the collection. Apache Commons has an implementation of it. Here's their interface, and here's a sorted tree implementation.

You'd do something like this:

Bag<Integer> bag = new TreeBag<Integer>();
for (int i = 0; i < numList.length; i++) {
    bag.add(numList[i]);
}
for (int uniqueNumber: bag.uniqueSet()) {
    System.out.println("Number " + uniqueNumber + " counted " + bag.getCount(uniqueNumber) + " times");
}

The example above takes elements from your numList array and adds them to the Bag for purposes of generating the counts, but de rigueur you don't even need the array. Just add the elements to the Bag directly. Something like:

// Make your bag.
Bag<Integer> bag = new TreeBag<Integer>();

...

// Populate your bag.
for (num = 0; num < MAX_NUM; num++) {
    bag.add(scan.nextInt());
}

...

// Print the counts for each unique item in your bag.
for (int uniqueNumber: bag.uniqueSet()) {
    System.out.println("Number " + uniqueNumber + " counted " + bag.getCount(uniqueNumber) + " times");
}
like image 33
Andre Gregori Avatar answered Oct 24 '22 15:10

Andre Gregori


What I have to say is, it took me a while to figure out what the two variables count and countNum represent for, maybe some comments are needed. But finally I find out the bug.

Suppose input ten numbers are: 5, 6, 7, 8, 5, 6, 7, 8, 5, 6

After sort, numList is : 5, 5, 5, 6, 6, 6, 7, 7, 8, 8

The array count returned by occurrences()should be: [1, 2, 3, 1, 2, 3, 1, 2, 1, 2]

Actually the only useful numbers in this result array are:

count[2]: 3     count number for numList[2]: 5
count[5]: 3     count number for numList[5]: 6
count[7]: 2     count number for numList[7]: 7
count[9]: 2     count number for numList[9]: 8

The other numbers, like the first two numbers 1, 2 before 3, are only used to calculate the sum occurrences incrementally, right? So, your loop logic should be changed as following:

  1. remove the first if code block:

    if (num == 0)
    {
       if (count[num] <= 1)
          System.out.println (numList[num] + " occurs " + count[num] + " time");
    
       if (count[num] > 1)
          System.out.println (numList[num] + " occurs " + count[num] + " times");
    } 
    
  2. Change the second if condition to:

    if ((num + 1) == MAX_NUM || numList[num] != numList[num + 1]) {
        ......
    }
    

After this, your code should work well as expected.

BTW, you really don't need to do it so intricately. Just try HashMap :)

like image 24
JasonZhao Avatar answered Oct 24 '22 16:10

JasonZhao