ChatGPT:为什么计数排序需要进行累加操作
第一种写法
private static void countSort() {
int[] MaxMin = findMaxMin();
int max = MaxMin[0];
int min = MaxMin[1];
int[] counts = new int[max - min + 1];
for (int num : nums) {
counts[num - min]++;
}
int index = 0;
for (int i = 0; i < counts.length; i++) {
while (counts[i] > 0) {
nums[index++] = min + i;
counts[i]--;
}
}
System.out.println(Arrays.toString(nums));
}
private static int[] findMaxMin() {
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for (int num : nums) {
if (num > max) {
max = num;
}
if (num < min) {
min = num;
}
}
return new int[]{max, min};
}
第二种写法
/**
* Gets the maximum and minimum values in the array
*
* @param arr
* @return
*/
private static int[] getMinAndMax(int[] arr) {
int maxValue = arr[0];
int minValue = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > maxValue) {
maxValue = arr[i];
} else if (arr[i] < minValue) {
minValue = arr[i];
}
}
return new int[] { minValue, maxValue };
}
/**
* Counting Sort
*
* @param arr
* @return
*/
public static int[] countingSort(int[] arr) {
if (arr.length < 2) {
return arr;
}
int[] extremum = getMinAndMax(arr);
int minValue = extremum[0];
int maxValue = extremum[1];
int[] countArr = new int[maxValue - minValue + 1];
int[] result = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
countArr[arr[i] - minValue] += 1;
}
for (int i = 1; i < countArr.length; i++) {
countArr[i] += countArr[i - 1];
}
for (int i = arr.length - 1; i >= 0; i--) {
int idx = countArr[arr[i] - minValue] - 1;
result[idx] = arr[i];
countArr[arr[i] - minValue] -= 1;
}
return result;
}
为什么要累积计数(对计数数组 countArr 进行累积,得到每个值的最终位置索引)这相对于第一个方法有什么优化?
累积计数是为了确保基数排序(Counting Sort)的稳定性,并且直接构建出排序后的新数组。以下是累积计数的具体优势及其相对于第一个方法的优化:
1. 稳定性
稳定性指的是在排序过程中,相同的元素保持其原有的相对顺序。累积计数的步骤确保了这一点:
- 累积计数:累积计数数组
countArr
记录了每个元素在最终排序数组中的位置索引。这意味着当我们从右向左遍历原数组时,相同元素会按照原有的顺序被放置到结果数组中。 - 稳定排序:这种方法保证了排序的稳定性,使得相同的元素在排序后保持相对位置不变。这在处理需要稳定排序的情况下(如基于某个关键字排序的多级排序)特别有用。
2. 直接构建排序后的新数组
- 新数组:累积计数方法直接构建了一个新的排序数组
result
。这避免了对原数组的多次操作,提高了代码的清晰度和可维护性。 - 相对索引:累积计数数组
countArr
的值表示原数组中每个元素的最终位置。这使得我们可以一次性将元素放置到正确的位置,避免了在原数组上进行多次遍历和修改。