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


    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 

  • 相关阅读:
    json&display
    postgresql AutoVacuum系统自动清理进程
    postgresql vacuum操作
    C++ 在.h文件中包含头文件和在.cpp文件中包含头文件有什么区别
    ResetEvent、CreateEvent、SetEvent
    《转载》C语言的移位操作符
    《转载》如何使用M6117D看门狗定时器复位系统
    《转载》 Bit,Byte,WORD,DWORD区别和联系
    $.messager.alert
    对一个或多个实体的验证失败
  • 原文地址:https://www.cnblogs.com/jiangchen/p/5935343.html
Copyright © 2020-2023  润新知