public static void countingSort(Integer array[]) {

        if (array.length == 0)
            return;

        /** find max and min values **/
        int max = array[0], min = array[0];

        for (int i = 0; i < array.length; i++)
        {
            if (array[i] > max)
                max = array[i];

            if (array[i] < min)
                min = array[i];
        }

        final int range = max - min + 1;

        /** check if range is small enough for count array **/
        /** else it might give out of memory exception while allocating memory for array **/
        if (range > MAX_RANGE)
        {
            System.out.println("\nError : Range too large for sort");
            return;

        }
        Integer counts[] = new Integer[range];
        Integer output[] = new Integer[array.length];

        Arrays.fill(counts, 0);

        // histogram
        // how many of each element is there ?
        for (int i = 0; i < array.length; ++i) {
            counts[array[i]-min] += 1;
        }

        // accumulate - "prefix sum" counts[i] contains # of values <=
        // counts[i]
        // it instead stores the number of items with key less than i,
        // which is the same as the first index at which an item with key i should be stored in the output array.
        for (int i = 1; i < range; ++i) {
            counts[i] += counts[i - 1];
        }

        // create sorted output
        for (int i = 0 ; i < array.length; i++) {
            counts[array[i] - min] -= 1; // decrement count
            //System.out.println("# items <= " + array[i] + " is " + counts[array[i] - min]);
            //System.out.println("setting output index " + counts[array[i] - min] + " to " + array[i]);
            output[counts[array[i] - min]] = array[i];

        }

        // copy output back to array
        System.arraycopy( output, 0, array, 0, array.length );
    }