912. Sort an Array
排序
排序大体可分为两类,基于比较的和不基于比较的。
计数排序,桶排序和基数排序不基于比较。
- 冒泡排序 bubble sort
对于相邻两个数,如果前者大于后者,交换
完成一轮后会选出一个最大的
需要交换多少次?求逆序对个数
class Solution {
public int[] sortArray(int[] nums) {
if (nums == null || nums.length == 0) return new int[0];
bubbleSort(nums);
return nums;
}
private void bubbleSort(int[] nums) {
//如果最后一个num最小,将其移动到最前面需要 n-1 steps
for (int i = nums.length-1; i > 0; i--) {
boolean isSorted = true;
for (int j = 0; j + 1 <= i; j++) {
if (nums[j+1] < nums[j]) {
swap(nums, j, j+1);
isSorted = false; //这一次loop发生了排序
}
}
if (isSorted) break;
}
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
- 选择排序 selection sort
class Solution {
public int[] sortArray(int[] nums) {
if (nums == null || nums.length == 0) return new int[0];
selectionSort(nums);
return nums;
}
private void selectionSort(int[] nums) {
//每次在[i, n-1]中选择一个最小的, 放到i
for (int i = 0; i < nums.length; i++) {
int minIdx = i;
for (int j = i; j < nums.length; j++) {
if (nums[minIdx] > nums[j]) {
minIdx = j;
}
}
swap(nums, minIdx, i);
}
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
- 插入排序 insertion sort
class Solution {
public int[] sortArray(int[] nums) {
if (nums == null || nums.length == 0) return new int[0];
inertionSort(nums);
return nums;
}
private void inertionSort(int[] nums) {
//选第i个,插入到[0, i-1]中
for (int i = 1; i < nums.length; i++) {
int t = nums[i];
int j = i-1;
while (j >= 0 && nums[j] > t) {
nums[j+1] = nums[j];
j--;
}
nums[j+1] = t;
}
}
}
- 归并排序 merge sort
148. Sort List
mergeSort和堆排序是唯二的worst case是O(n log n)
并且mergeSort是稳定的
class Solution {
public int[] sortArray(int[] nums) {
if (nums == null || nums.length == 0) return new int[0];
mergeSort(0, nums.length-1, nums);
return nums;
}
private void mergeSort(int lo, int hi, int[] nums) {
if (lo >= hi) {
return;
}
int mid = lo + (hi - lo) / 2;
mergeSort(lo, mid, nums);
mergeSort(mid+1, hi, nums);
merge(lo, mid, hi, nums);
}
private void merge(int lo, int mid, int hi, int[] nums) {
int[] temp = new int[hi-lo+1];
int i = lo, j = mid + 1, k = 0;
while (i <= mid && j <= hi) {
if (nums[i] < nums[j]) {
temp[k++] = nums[i++];
} else {
temp[k++] = nums[j++];
}
}
while (i <= mid) {
temp[k++] = nums[i++];
}
while (j <= hi) {
temp[k++] = nums[j++];
}
for (int idx = lo; idx <= hi; idx++) {
nums[idx] = temp[idx - lo];
}
}
}
- 快速排序 quick sort
//模板一
class Solution {
public int[] sortArray(int[] nums) {
if (nums == null || nums.length == 0) return new int[0];
quickSort(nums, 0, nums.length-1);
return nums;
}
private void quickSort(int[] nums, int l, int r) {
if (l >= r) return;
int i = l-1, j = r+1, m = l+(r-l)/2;
int x = nums[m];
while (i < j) {
do i++; while (nums[i] < x);
do j--; while (nums[j] > x);
if (i < j) {
swap(nums, i, j);
} else {
quickSort(nums, l, j);
quickSort(nums, j+1, r);
}
}
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
//模板二
class Solution {
Random rand = new Random();
public int[] sortArray(int[] nums) {
if (nums == null || nums.length == 0) return new int[0];
quickSort(nums, 0, nums.length-1);
return nums;
}
private void quickSort(int[] nums, int l, int r) {
if (l >= r) return;
int p = partition(nums, l, r);
quickSort(nums, l, p-1);
quickSort(nums, p+1, r);
}
private int partition(int[] nums, int l, int r) {
//随机化快排
int p = l + rand.nextInt(r-l+1); //[0, r-l] + l = [l, r]
int pivot = nums[p];
swap(nums, p, l);
// int pivot = nums[l];
p = l+1;
for (int i = l+1; i <= r; i++) {
if (nums[i] < pivot) {
swap(nums, i, p++);
}
}
swap(nums, l, p-1);
return p-1;
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
//基于链表的快速排序
- 堆排序 heap sort
class Solution {
//用一个大根堆,每次取出最大的放在最后面
public int[] sortArray(int[] nums) {
if (nums == null || nums.length == 0) return new int[0];
heapSort(nums, nums.length);
return nums;
}
private void heapSort(int[] nums, int n) {
buildHeap(nums, n);
//每次将顶部和最后一个交换,再对顶部做heapify
for (int i = n-1; i >= 0; i--) {
//每次swap完,与顶部交换的就是最大的
swap(nums, 0, i);
//最后一部分[i, n-1]就是sorted的了,只需对[0, i-1] (长度为i) 做heapify
heapify(nums, 0, i);
}
}
//从倒数第二层向上每个点做heapify
private void buildHeap(int[] nums, int n) {
int lastNode = nums.length - 1;
int f = (lastNode - 1) / 2;
for (int i = f; i >= 0; i--) {
heapify(nums, i, n);
}
}
//确保i和i的子树是一个min—heap
private void heapify(int[] nums, int i, int n) {
int max = i;
int c1 = 2*i+1;
int c2 = 2*i+2;
if (c1 < n && nums[max] < nums[c1]) {
max = c1;
}
if (c2 < n && nums[max] < nums[c2]) {
max = c2;
}
if (max != i) {
swap(nums, max, i);
heapify(nums, max, n);
}
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
- 计数排序 counting sort
- 桶排序 bucket sort
- 基数排序 radix sort
164. Maximum Gap