0912. 排序数组 #
- 标签:数组、分治、桶排序、计数排序、基数排序、排序、堆(优先队列)
- 难度:中等
题目大意 #
描述:给定一个整数数组 nums
。
要求:将该数组升序排列。
说明:
- $1 \le nums.length \le 5 * 10^4$。
- $-5 * 10^4 \le nums[i] \le 5 * 10^4$。
示例:
- 示例 1:
|
|
- 示例 2:
|
|
解题思路 #
这道题是一道用来复习排序算法,测试算法时间复杂度的好题。我试过了十种排序算法。得到了如下结论:
- 超时算法(时间复杂度为 $O(n^2)$):冒泡排序、选择排序、插入排序。
- 通过算法(时间复杂度为 $O(n \times \log_2 n)$):希尔排序、归并排序、快速排序、堆排序。
- 通过算法(时间复杂度为 $O(n)$):计数排序、桶排序。
- 解答错误算法(普通基数排序只适合非负数):基数排序。
思路 1:冒泡排序(超时) #
冒泡排序(Bubble Sort)基本思想:
- 第
i (i = 1, 2, …)
趟排序时从序列中前n - i + 1
个元素的第1
个元素开始,相邻两个元素进行比较,如果前者大于后者,两者交换位置,否则不交换。
思路 1:代码 #
|
|
思路 1:复杂度分析 #
- 时间复杂度:$O(n^2)$。
- 空间复杂度:$O(1)$。
思路 2:选择排序(超时) #
选择排序(Selection Sort)基本思想:
- 将序列分为两部分:前边
i - 1
个元素为已排序部分,后边n - i + 1
个元素为未排序部分。 - 第
i
趟排序从未排序部分n − i + 1 (i = 1, 2, …, n − 1)
个元素中选择一个值最小的元素与未排序部分最前面那个元素交换位置,即与整个序列的第i
个位置上的元素交换位置。 - 如此下去,直到所有元素都变为已排序部分,排序结束。
思路 2:代码 #
|
|
思路 2:复杂度分析 #
- 时间复杂度:$O(n^2)$。
- 空间复杂度:$O(1)$。
思路 3:插入排序(超时) #
插入排序(Insertion Sort)基本思想:
- 将整个序列分为两部分:前面
i
个元素为有序序列,后面n - i
个元素为无序序列。 - 每一次排序,将无序序列的第
1
个元素,在有序序列中找到相应的位置并插入。
思路 3:代码 #
|
|
思路 3:复杂度分析 #
- 时间复杂度:$O(n^2)$。
- 空间复杂度:$O(1)$。
思路 4:希尔排序(通过) #
希尔排序(Shell Sort)基本思想:
- 将整个序列切按照一定的间隔取值划分为若干个子序列,每个子序列分别进行插入排序。
- 然后逐渐缩小间隔进行下一轮划分子序列和对子序列进行插入排序。
- 直至最后一轮排序间隔为
1
,对整个序列进行插入排序,完成排序。
思路 4:代码 #
|
|
思路 4:复杂度分析 #
- 时间复杂度:介于 $O(n \times \log_2 n)$ 与 $O(n^2)$ 之间。
- 空间复杂度:$O(1)$。
思路 5:归并排序(通过) #
归并排序(Merge Sort)基本思想:
- 采用经典的分治策略,先递归地将当前序列平均分成两半。
- 然后将有序序列两两合并,最终合并成一个有序序列。
思路 5:代码 #
|
|
思路 5:复杂度分析 #
- 时间复杂度:$O(n \times \log_2n)$。
- 空间复杂度:$O(n)$。
思路 6:快速排序(通过) #
快速排序(Quick Sort)基本思想:
- 通过一趟排序将无序序列分为独立的两个序列,第一个序列的值均比第二个序列的值小。
- 然后递归地排列两个子序列,以达到整个序列有序。
思路 6:代码 #
|
|
思路 6:复杂度分析 #
- 时间复杂度:$O(n \times \log_2 n)$。
- 空间复杂度:$O(n)$。
思路 7:堆排序(通过) #
堆排序(Heap sort)基本思想:
- 借用「堆结构」所设计的排序算法。
- 将数组转化为大顶堆,重复从大顶堆中取出数值最大的节点,并让剩余的堆结构继续维持大顶堆性质。
思路 7:代码 #
|
|
思路 7:复杂度分析 #
- 时间复杂度:$O(n \times \log_2 n)$。
- 空间复杂度:$O(1)$。
思路 8:计数排序(通过) #
计数排序(Counting Sort)基本思想:
- 使用一个额外的数组
counts
,其中counts[i]
表示原数组arr
中值等于i
的元素个数。 - 然后根据数组
counts
来将arr
中的元素排到正确的位置。
思路 8:代码 #
|
|
思路 8:复杂度分析 #
- 时间复杂度:$O(n + k)$。其中 $k$ 代表待排序序列的值域。
- 空间复杂度:$O(k)$。其中 $k$ 代表待排序序列的值域。
思路 9:桶排序(通过) #
桶排序(Bucket Sort)基本思想:
- 将未排序数组分到若干个「桶」中,每个桶的元素再进行单独排序。
思路 9:代码 #
|
|
思路 9:复杂度分析 #
- 时间复杂度:$O(n)$。
- 空间复杂度:$O(n + m)$。$m$ 为桶的个数。
思路 10:基数排序(提交解答错误,普通基数排序只适合非负数) #
基数排序(Radix Sort)基本思想:
- 将整数按位数切割成不同的数字,然后按每个位数分别比较进行排序。
思路 10:代码 #
|
|
思路 10:复杂度分析 #
- 时间复杂度:$O(n \times k)$。其中 $n$ 是待排序元素的个数,$k$ 是数字位数。$k$ 的大小取决于数字位的选择(十进制位、二进制位)和待排序元素所属数据类型全集的大小。
- 空间复杂度:$O(n + k)$。