# Sorting Algorithms

## Recursion

分析要点是： Base Case: Smallest Problem to Solve  &  Recursive Rule: How to make a problem smaller

### a^b

首先base case 是 b = 0 和 b = 1这两种情况，我们把问题不断拆分，即 2^1000 = 2^500 \* 2^500

```java
public int pow(int a, int b){
    if(b == 0){
        return 1;
    }
    if(b == 1){
        return a;
    }
    int halfResult = pow(a, b / 2);
    if(b % 2 == 0){
        return halfResult  * halfResult ;
    }else{
        return halfResult * halfResult * a
    }
}

由于不断把pow进行拆分，所以这里时间复杂度为O(log b)， 空间为 O(log b)
```

## Merge Sort

merge sort 就是把一个数组不断分拆分，直到拆为两两比较，再把它们合起来

&#x20;           3，1，5，7，9，8，6，4，2，0

&#x20;             31579                      86420                       O(1)   这个是找到中点，并把数组分为两类所需要的时间

&#x20;      315             79           864                20            O(2)

31           5   7          9   86      4            2          0    O(4)

因此，分开的时间是 1 + 2 + 4 + ... + n/2  = O(n)  (对这个式子+1 -1 即可)

而需要的空间则是 n + n/2 + n/4 + .... + 1 = O(n)

完成分割之后，则进行合并，每次合并的总时间为O(n)， 在这里我们被分割为logn 层，所以总的合并时间为O(nlogn)

```java
public int[] mergeSort(int[] array, int n){
    if(n < 2){
        return a;
    }
    int mid = n / 2;
    int[] l = new int[mid];
    int[] r = new int[n-mid];
    for(int i = 0; i < mid; i++){
        l[i] = array[i];
    }
    for(int i = mid; i < end; i++){
        r[i-mid] = array[i];
    }
    mergeSort(l, mid);
    mergeSort(r, n-mid);
    merge(array, l, r, mid, n-mid)
    
}
public void merge(
  int[] a, int[] l, int[] r, int left, int right) {
  
    int i = 0, j = 0, k = 0;
    while (i < left && j < right) {
        if (l[i] <= r[j]) {
            a[k++] = l[i++];
        }
        else {
            a[k++] = r[j++];
        }
    }
    while (i < left) {
        a[k++] = l[i++];
    }
    while (j < right) {
        a[k++] = r[j++];
    }
}
```

## Quick Sort

```java
public Solution{
    public int[] quickSort(int[] array){
        if(array == null){
            return array;
        }
        quickSort(array, 0, array.length - 1);
        return array;
    }
    
    public void quickSort(int[] array, int left, int right){
    if (left >= right) {
      return;
    }
    int pivotIdx = partition(array, left, right);
    quickSort(array, left, pivotIdx-1);
    quickSort(array, pivotIdx+1, right);
  }
  
    private void partition(int[] array, int start, int end){
        int pivotIdx = start + (int)(Math.random()*(end- start));
        int pivot    = array[pivotIdx];
        swap(array, pivot, end);
        int leftBound = start;
        int rightBound = end - 1;
        while(leftBound <= rightBount){
            if(arrat[leftBound] < pivot){
                leftBound++;
            }else{
                swap(array, leftBound, rightBound);
                rightBound--;
            }
        }
        swap(array, leftBound, end);
        return leftBound;
    }
}
```
