各种排序笔记---基于比较排序部分

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;
  }
}
Selection sort

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];
            }
        }
merge sort array

复杂度分析:

                         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 index
        int pivot = A[(start + end) / 2];

        // key point 2: every time you compare left & right, it should be 
        // left <= right not left < right
        while (left <= right) {
            // key point 3: A[left] < pivot not A[left] <= pivot
            while (left <= right && A[left] < pivot) {
                left++;
            }
            // key point 3: A[right] > pivot not A[right] >= pivot
            while (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);
    }
}
array quick sort

伪代码:

function quicksort(q)
     var list less, pivotList, greater
     if length(q) ≤ 1 {
         return q
     } else {
         select a pivot value pivot from q
         for each x in q except the pivot element
             if x < pivot then add x to less
             if x ≥ pivot then add x to greater
         add pivot to pivotList
         return 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 it
        ListNode 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 null
        leftTail.next = null;
        middleTail.next = null;
        rightTail.next = null;
        
        //recurisive do the sort
        ListNode left = sortList(leftDummy.next);
        ListNode right = sortList(rightDummy.next);
        
        //connect the three parts together
        return 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;
    }
}
sortList

相关题目整理: //to do 

原文地址:https://www.cnblogs.com/jiangchen/p/5935343.html