目录
计数排序详解
面试题 75 : 数组相对排序
计数排序详解
计数排序是一种线性时间的整数排序算法,其算法步骤为:
-
找出待排序数组 nums 中的最小值和最大值(分别用 min 和 max 表示)。
-
创建一个长度为 max - min + 1、元素初始值全为 0 的计数器数组 count。
-
扫描一遍原始数组,将 nums[i] - min 作为下标,并将该下标的计数器增加 1。
-
扫描一遍计数器数组,按顺序把值收集起来。
排序数组:
class Solution {
public:vector<int> sortArray(vector<int>& nums) {int min = nums[0], max = nums[0];for (int i = 1; i < nums.size(); ++i){if (nums[i] < min)min = nums[i];if (nums[i] > max)max = nums[i];}
vector<int> counts(max - min + 1, 0);for (int i = 0; i < nums.size(); ++i){++counts[nums[i] - min];}
int j = 0;for (int i = 0; i < max - min + 1; ++i){while (counts[i] > 0){nums[j++] = i + min;--counts[i];}}return nums;}
};
如果数组的长度为 n,整数的范围(即数组中最大整数和最小整数的差值再加 1)为 k,那么计数排序的时间复杂度就是 O(n + k)。由于需要创建一个长度为 O(k) 的计数器数组 counts,因此空间复杂度为 O(k)。
当 k 比较小时,无论从时间复杂度还是空间复杂度来看都是比较高效的算法。当 k 很大时,计数排序可能就不如其他排序算法(如快速排序、归并排序)高效。
面试题 75 : 数组相对排序
题目:
输入两个数组 arr1 和 arr2,其中数组 arr2 中的每个数字都唯一,并且都是数组 arr1 中的数字。请将数组 arr1 中的数字按照数组 arr2 中的数字的相对顺序排序。如果数组 arr1 中的数字在数组 arr2 中没有出现,那么将这些数字按递增的顺序排在后面。假设数组中的所有数字都在 0 到 1000 的范围内。例如,输入的数组 arr1 和 arr2 分别是 [2, 3, 3, 7, 3, 9, 2, 1, 7, 2] 和 [3, 2, 1],则数组 arr1 排序之后为 [3, 3, 3, 2, 2, 2, 1, 7, 7, 9]。
分析:
题目明确提出数组中的数字都在 0 到 1000 的范围内,这是一个很明显的提示,据此可以考虑采用计数排序。
代码实现:
class Solution {
public:vector<int> relativeSortArray(vector<int>& arr1, vector<int>& arr2) {int min = arr1[0], max = arr1[0];for (int i = 1; i < arr1.size(); ++i){if (arr1[i] < min)min = arr1[i];if (arr1[i] > max)max = arr1[i];}
vector<int> counts(max - min + 1, 0);for (int i = 0; i < arr1.size(); ++i){++counts[arr1[i] - min];}
int i = 0;for (int num : arr2){while (counts[num - min] > 0){arr1[i++] = num;--counts[num - min];}}
for (int j = 0; j < max - min + 1; ++j){while (counts[j] > 0){arr1[i++] = j + min;--counts[j];}}return arr1;}
};