912. Sort an Array
排序
排序大體可分為兩類妄荔,基于比較的和不基于比較的泼菌。
計(jì)數(shù)排序,桶排序和基數(shù)排序不基于比較啦租。
- 冒泡排序 bubble sort
對于相鄰兩個數(shù)哗伯,如果前者大于后者,交換
完成一輪后會選出一個最大的
需要交換多少次篷角?求逆序?qū)€數(shù)
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發(fā)生了排序
}
}
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是穩(wěn)定的
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) {
//隨機(jī)化快排
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);
}
}
//從倒數(shù)第二層向上每個點(diǎn)做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;
}
}
- 計(jì)數(shù)排序 counting sort
- 桶排序 bucket sort
- 基數(shù)排序 radix sort
164. Maximum Gap