1. 选择排序 selection sort
大循环 从左到右每次以一个点开始扫描array
小循环 找到从当前起始点开始的最小值
时间复杂度为O(N^2)
//selection sort an array array[] public class Solution {public int[] solve(int[] array) {if (array == null || array.length == 0) {return array;}for (int i = 0; i < array.length - 1; i++) {int gobalMin = i;for (int j = i + 1; j < array.length; j++) {if (array[j] < array[gobalMin]) {gobalMin = j;}}swap(array, i, gobalMin);}return array;}private void swap(int[] array, int i, int j) {int temp = array[i];array[i] = array[j];array[j] = temp;} }
2. 归并排序 Merge sort
归并排序是基于一种被称为“分治”(divide and conquer)的策略。
Merge sort array:
public int[] mergeSort(int[] array) {if (array == null || array.length == 0) {return array;}int[] temp = new int[array.length];mergeSortHelper(array, 0, array.length - 1, temp);return array;}private void mergeSortHelper(int[] array, int start, int end, int[] temp) {if (start == end) {return;}int mid = start + (end - start) / 2;mergeSortHelper(array, start, mid, temp);mergeSortHelper(array, mid + 1, end, temp);merge(array, start, mid, end, temp);}private void merge(int[] array, int start, int mid, int end, int[] temp) {int left = start;int right = mid + 1;int index = start;while (left <= mid && right <= end) {if (array[left] < array[right]) {temp[index++] = array[left++];} else {temp[index++] = array[right++];}}while (left <= mid) {temp[index++] = array[left++];}while (right <= end) {temp[index++] = array[right++];}for (index = start; index <= end; index++) {array[index] = temp[index];}}
复杂度分析:
1 2 3 4 5 6 7 8
/ 当前层拆分需要劈1刀 O(1)
1 2 3 4
/ 当前层拆分需要劈2刀 O(2)
12 ...
/
1 当前层拆分需要劈n /2刀
1 + 2 + 4 + 8+ ... + n/2 -> n = O(n) 可以这样理解,终极状态下每个数字被切分成一个单位,n个数字,需要被切n-1刀
所以devide and conquer的上半部分的时间复杂度是O(n) 而不是log(n)
空间复杂度:考虑计算机里面只要保存的额外开销,其实是粉色部分,因为在任意时刻,计算机只有一个确定的状态,call stack在同一个确定的层只能保留部分的结果。比如最底层只能保留1,或者保留2,而不会1,2同时在栈里面!
所以空间复杂度:1 + 2 + 4 + 8 + ... + n = O(2n) = O(n)
==============================================
devide and conquer的上半部分,merge 部分, totoal time complexity is O(nlogn):
1 2 3 4 5 6 7 8
\/ \/ \/ \/ this level time complexity is O(n)
12 34 56 78
\ / \ / this level time complexity is O(n)
1234 5678
\ / this level time complexity is O(n)
12345678
3. 快速排序
Array quick sort:
重点在于理解左右两个挡板的物理意义!!!
a. [0,....., left]: left 的左侧(不包含left)全部为比pivot小的数
b. [left, right]: left 和 right之间为未探索的区域
c. [right, ..... n-1]: right的右侧(不包含)全部为比pivot大或者等于的数字
public class Solution {/*** @param A an integer array* @return void*/public void sortIntegers2(int[] A) {quickSort(A, 0, A.length - 1);}private void quickSort(int[] A, int start, int end) {if (start >= end) {return;}int left = start, right = end;// key point 1: pivot is the value, not the indexint pivot = A[(start + end) / 2];// key point 2: every time you compare left & right, it should be // left <= right not left < rightwhile (left <= right) {// key point 3: A[left] < pivot not A[left] <= pivotwhile (left <= right && A[left] < pivot) {left++;}// key point 3: A[right] > pivot not A[right] >= pivotwhile (left <= right && A[right] > pivot) {right--;}if (left <= right) {int temp = A[left];A[left] = A[right];A[right] = temp;left++;right--;}}quickSort(A, start, right);quickSort(A, left, end);} }
伪代码:
function quicksort(q)var list less, pivotList, greaterif length(q) ≤ 1 {return q} else {select a pivot value pivot from qfor each x in q except the pivot elementif x < pivot then add x to lessif x ≥ pivot then add x to greateradd pivot to pivotListreturn concatenate(quicksort(less), pivotList, quicksort(greater))}
Linkedlist quick sort
public class Solution {public ListNode sortList(ListNode head) {if (head == null || head.next == null) {return head;}ListNode mid = findMedian(head); // O(n)//new three dummmy node with a tail point to itListNode leftDummy = new ListNode(0), leftTail = leftDummy;ListNode rightDummy = new ListNode(0), rightTail = rightDummy;ListNode middleDummy = new ListNode(0), middleTail = middleDummy;//sprate to three part while (head != null) {if (head.val < mid.val) {leftTail.next = head;leftTail = head;} else if (head.val > mid.val) {rightTail.next = head;rightTail = head;} else {middleTail.next = head;middleTail = head;}head = head.next;}//make the tail to nullleftTail.next = null;middleTail.next = null;rightTail.next = null;//recurisive do the sortListNode left = sortList(leftDummy.next);ListNode right = sortList(rightDummy.next);//connect the three parts togetherreturn concat(left, middleDummy.next, right);}private static ListNode findMedian(ListNode head) {ListNode fast = head.next;ListNode slow = head;while (fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;}return slow;}private static ListNode concat(ListNode left, ListNode mid, ListNode right) {ListNode dummy = new ListNode(0), dummyTail = dummy;dummyTail = connect(dummyTail, left);dummyTail = connect(dummyTail, mid);dummyTail = connect(dummyTail, right);return dummy.next;}private static ListNode connect(ListNode dummyTail, ListNode current) {while (current != null) {dummyTail.next = current;dummyTail = dummyTail.next;current = current.next;}return dummyTail;} }
相关题目整理: //to do