简体   繁体   中英

Counting occurrences of integers in an array in Java

Note: no mapping, no sorting

Here's my code:

public static void countArray(int[] n){
    int[] m = new int[n.length]; //50 elements of integers between values of 10 & 20
    int count = 0;
    int sum = 0;

    for ( int i = 0; i < n.length ; i++){
        m[i] = n[i]; //make a copy of array 'n'
        System.out.print(m[i]+" ");

    }System.out.println();

    for ( int j =0; j < n.length ; j++){
        count =0;
        for(int i = 0; i < n.length ; i++){
            if (n[j]%m[i]==0 && n[j] == m[i])
                count++;
        }if ( n[j]%m[j] == 0)
        System.out.println(m[j] + " occurs = " + count);
    }   
}

So the problem is: I get repeating results like : "25 occurs = 5", on different lines.

What I think: the problem occurs because of if ( n[j]%m[j] == 0) so I tried if ( n[j]%m[j+1] == 0) . Another problem occurs since m[j] will be m[50] so it crashes but sort of give me the results that I want.

Result that I want: something like this: no repetitions and covers all the random integers on a set

17 occurs = 3
23 occurs = 2
19 occurs = 3
15 occurs = 2
12 occurs = 2

try this :(sort the array and then count the occurence of element)

public static void countArray(int[] n) {
    int count = 0;
    int i, j, t;
    for (i = 0; i < n.length - 1; i++) // sort the array
    {
        for (j = i + 1; j < n.length; j++) {
            if (n[i] > n[j]) {
                t = n[i];
                n[i] = n[j];
                n[j] = t;
            }

        }
    }

    for (i = 0; i < n.length;)
    {
        for (j = i; j < n.length; j++) {
            if (n[i] == n[j])
            {
                count++;
            } else
                break;
        }
        System.out.println(n[i] + " occurs " + count);
        count = 0;
        i = j;

    }

}

With some adaptation your code should work :

public static void countArray(int[] n){
    boolean [] alreadyCounted = new boolean[n.length]; 

    for (int i = 0; i < n.length ; i++){
        int count = 0;
        if (alreadyCounted[i]) {
            // skip this one, already counted
            continue;
        }
        for(int j = 0; j < n.length ; j++){
            if (n[i] == n[j]) {
                // mark as already counted
                alreadyCounted[j] = true;
                count++;
            }
        }
        System.out.println(n[i] + " occurs = " + count);
    }   
}

You could definitely use the same logic with better code, I just tried to follow the original "coding style";

This is O(n^2) solution (read "very slow" ).
If you could use sorting, you could do it in O(n log(n)) - that is fast .
With mapping you could do it in O(n) - that is blazingly fast ;

If you exploit the input limit you can lose the nested loop:

public static void main(String[] args)
{
    //6 elements of integers between values of 10 & 20
    int[] countMe = { 10, 10, 20, 10, 20, 15 };

    countArray(countMe);
}

/** Count integers between values of 10 & 20 (inclusive) */
public static void countArray(int[] input)
{
    final int LOWEST = 10;
    final int HIGHEST = 20;

    //Will allow indexes from 0 to 20 but only using 10 to 20
    int[] count = new int[HIGHEST + 1]; 

    for(int i = 0; i < input.length; i++)
    {
        //Complain properly if given bad input
        if (input[i] < LOWEST || HIGHEST < input[i])
        {
            throw new IllegalArgumentException("All integers must be between " +
                    LOWEST + " and " + HIGHEST + ", inclusive");
        }

        //count
        int numberFound = input[i]; 
        count[numberFound] += 1;
    }

    for(int i = LOWEST; i <= HIGHEST; i++)
    {
        if (count[i] != 0) 
        {
            System.out.println(i + " occurs = " + count[i]);
        }
    }
}   

Here's a nice, efficient way to do it, rather more efficiently than the other solutions posted here. This one runs in O(n) time, where the array is of length n. It assumes that you have some number MAX_VAL , representing the maximum value that you might find in your array, and that the minimum is 0. In your commenting you suggest that MAX_VAL==20 .

public static void countOccurrences(int[] arr) {
    int[] counts = new int[MAX_VAL+1];
    //first we work out the count for each one
    for (int i: arr)
        counts[i]++;
    //now we print the results
    for (int i: arr)
        if (counts[i]>0) {
            System.out.println(i+" occurs "+counts[i]+" times");
            //now set this count to zero so we won't get duplicates
            counts[i]=0;
        }
}

It first loops through the array increasing the relevant counter each time it finds an element. Then it goes back through, and prints out the count for each one. But, crucially, each time it prints the count for an integer, it resets that one's count to 0, so that it won't get printed again.

If you don't like the for (int i: arr) style, this is exactly equivalent:

public static void countOccurrences(int[] arr) {
    int[] counts = new int[MAX_VAL+1];
    //first we work out the count for each one
    for (int i=0; i<arr.length; i++)
        counts[arr[i]]++;
    //now we print the results
    for (int i=0; i<arr.length; i++)
        if (counts[arr[i]]>0) {
            System.out.println(arr[i]+" occurs "+counts[arr[i]]+" times");
            //now set this count to zero so we won't get duplicates
            counts[arr[i]]=0;
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM