排序算法 | 时间复杂度(最好) | 时间复杂度(最坏) | 时间复杂度(平均) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(N) | O(N2) | O(N2) | O(1) | 稳定 |
选择排序 | O(N2) | O(N2) | O(N2) | O(1) | 不稳定 |
插入排序 | O(N) | O(N2) | O(N2) | O(1) | 稳定 |
希尔排序 | 取决于增量序列 | O(N2) | 取决于增量序列 | O(1) | 不稳定 |
快速排序 | O(N2) | O(NlogN) | O(NlogN) | O(logN) | 不稳定 |
归并排序 | O(NlogN) | O(NlogN) | O(NlogN) | O(N) |
|
堆排序 | O(NlogN) | O(NlogN) | O(NlogN) | O(1) | 不稳定 |
计数排序 | |||||
桶排序 |
冒泡排序
冒泡排序是不断比较相邻两个元素,并不断交换,最后把大的放到数组后面。第一趟遍历会把最大的元素放到(n-1)位置,第二趟遍历会把第二大的元素放到(n-2)的位置,以此类推。
public int[] sortArray(int[] nums) { for(int i = 0; i < nums.length - 1; i++) { boolean isSorted = true; for(int j = 0; j < nums.length - i - 1; j++){ if(nums[j] > nums[j + 1]) { swap(nums, j, j + 1); isSorted = false; } } if(isSorted) break; } return nums;}private void swap(int[] nums, int i, int j){ int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp;}
最好的情况是当数组有序,跑一次内存循环(时间复杂度为O(N)
)后,因为isSorted
为true
,外层循环直接退出。所以时间复杂度为O(N)。
选择排序
选择排序要进行N-1趟,每次把当前最小的元素放到数组左边。第p趟过后,数组第0到第p-1都是有序的。
插入排序
跟玩扑克牌的时候,整理牌的操作很像。
插入排序由N-1趟排序组成。在第p趟,我们将位置p上的元素不断和它左边的元素比较,直到把这个元素放在合适的位置。第p趟排序之后,数组的第0至第p位置上的元素变为已排序状态。
public int[] sortArray(int[] nums) { for(int p = 1; p < nums.length; p++){ int tmp = nums[p]; int j; for(j = p - 1; j >= 0 && tmp < nums[j]; j--) nums[j + 1] = nums[j]; nums[j + 1] = tmp; } return nums;}
最好的情况是当数组有序,内层循环立即不成立而终止,所以时间复杂度为O(N)。
希尔排序
希尔排序是基本的插入排序的改进。它有一个增量序列,如1, 3, 5...
在使用增量序列hk排序后,对于每一个i都有nums[i] <= nums[i + hk]。
归并排序
Leetcode 912. Sort an Array, 你可以用你学过的所有的排序算法来做一下这道题。