public class CountingSort {
	public static int[] countingSort(int[] unsorted) {
		int minValue = min(unsorted);
		int maxValue = max(unsorted);

		// Adjust max so that min equals zero
		int offset = -minValue;
		int adjustedMax = maxValue + offset;

		// Count occurrences of each value in unsorted
		int[] counts = new int[adjustedMax + 1];

		for(int value : unsorted)
			counts[value + offset]++;

		for(int i = 1; i < counts.length; i++)
			counts[i] += counts[i - 1];

		// Reorder values in unsorted
		int[] sorted = new int[unsorted.length];
		for(int value : unsorted) {
			int index = --counts[value + offset];
			sorted[index] = value;
		}

		return sorted;
	}

	private static int min(int[] array) {
		int min = Integer.MAX_VALUE;

		for(int value : array)
			if(value < min) min = value;

		return min;
	}

	private static int max(int[] array) {
		int max = Integer.MIN_VALUE;

		for(int value : array)
			if(value > max) max = value;

		return max;
	}

	public static void main(String[] args) {
		int[] unsorted = {5, 5, 5, 4, 3, 2, 1, 0, -1, -2, -3, -3, -3};
		int[] sorted = countingSort(unsorted);
		for(int value : sorted)
			System.out.println(value);
	}
}
public class CountingSort {
	public static int[] countingSort(int[] unsorted) {
		int maxValue = max(unsorted);

		// Count occurrences of each value in unsorted
		int[] counts = new int[maxValue + 1];

		for(int value : unsorted)
			counts[value]++;

		for(int i = 1; i < counts.length; i++)
			counts[i] += counts[i - 1];

		// Reorder values in unsorted
		int[] sorted = new int[unsorted.length];
		for(int value : unsorted) {
			counts[value] -= 1;
			int index = counts[value];
			sorted[index] = value;
		}

		return sorted;
	}

	private static int max(int[] array) {
		int max = Integer.MIN_VALUE;

		for(int value : array) {
			if(value > max) max = value;
		}

		return max;
	}

	public static void main(String[] args) {
		int[] unsorted = {5, 5, 5, 4, 3, 2, 1, 0};
		int[] sorted = countingSort(unsorted);
		for(int value : sorted)
			System.out.println(value);
	}
}
--- 
+++ 
@@ -1,12 +1,17 @@
 public class CountingSort {
 	public static int[] countingSort(int[] unsorted) {
+		int minValue = min(unsorted);
 		int maxValue = max(unsorted);
 
+		// Adjust max so that min equals zero
+		int offset = -minValue;
+		int adjustedMax = maxValue + offset;
+
 		// Count occurrences of each value in unsorted
-		int[] counts = new int[maxValue + 1];
+		int[] counts = new int[adjustedMax + 1];
 
 		for(int value : unsorted)
-			counts[value]++;
+			counts[value + offset]++;
 
 		for(int i = 1; i < counts.length; i++)
 			counts[i] += counts[i - 1];
@@ -14,26 +19,33 @@
 		// Reorder values in unsorted
 		int[] sorted = new int[unsorted.length];
 		for(int value : unsorted) {
-			counts[value] -= 1;
-			int index = counts[value];
+			int index = --counts[value + offset];
 			sorted[index] = value;
 		}
 
 		return sorted;
 	}
 
+	private static int min(int[] array) {
+		int min = Integer.MAX_VALUE;
+
+		for(int value : array)
+			if(value < min) min = value;
+
+		return min;
+	}
+
 	private static int max(int[] array) {
 		int max = Integer.MIN_VALUE;
 
-		for(int value : array) {
+		for(int value : array)
 			if(value > max) max = value;
-		}
 
 		return max;
 	}
 
 	public static void main(String[] args) {
-		int[] unsorted = {5, 5, 5, 4, 3, 2, 1, 0};
+		int[] unsorted = {5, 5, 5, 4, 3, 2, 1, 0, -1, -2, -3, -3, -3};
 		int[] sorted = countingSort(unsorted);
 		for(int value : sorted)
 			System.out.println(value);
Allow counting sort to handle negative numbers
