Sorting

Bubble Sort

Bubble Sort requires n - 1 pass to sort an array of n elements.
In each pass every adjacent elements a[i] and a[i + 1] is compared and if they are not in order then they are swapped.
In each pass, we have n - k comparisons, where n is the number of elements and k is the pass number.
So 1st pass requires n - 1 comparisons, kth pass requires n - k comparisons and the last pass requires 1 comparison.

Time Complexity
O(n^2)
In 1st pass we have n - 1 comparisons, in 2rd we have n -2 comparisons, kth pass we have n - k comparisons, and the last pass requires 1 comparison.
F(n) = (n -1) + (n - 2) + .... + 3 + 2 + 1 = n(n - 1)/2 = O(n^2)
Space Complexity
O(1)

public void sortIntegers(int[] A) {
    // Write your code here
    if(A == null || A.length <= 1) return;
    for(int i = 0; i < A.length; i++){
        for(int j = 1; j < A.length - i; j++){
            if(A[j] < A[j - 1]) swap(A, j , j - 1);
        }
    }
    return;
}

private void swap(int[] A, int i , int j){
    int temp = A[i];
    A[i] = A[j];
    A[j] = temp;
}

Insertion Sort

In pass1, element a[1] is inserted either before or after a[0] so that a[0] and a[1] are sorted.
In pass2, a[2] is inserted either before a[0] or between a[0] and a[1] or after a[1] so that a[0], a[1] and a[2] are sorted.

It process is carried out n - 1 times.

Time Complexity
O(N^2)
F(n) = 1 + 2 + 3 + ... + (n - 2) + (n -1) = n(n - 1)/2 = O(N^2)
Insertion sort requires n - 1 pass to sort an array of n elements.
In each pass we have k comparisons, where k is the pass number.
So, 1st pass requires 1 comparison, kth pass requires k - 1 comparisons and the last pass requires n - 1 comparisons.

public void sortIntegers(int[] A) {
    // Write your code here
    if(A == null || A.length <= 1) return;
    int len = A.length;
    int j = 0, temp = 0;
    for(int i = 1; i < len; i++){
        j = i - 1;
        temp = A[i];
        while(j >= 0){
            if(temp < A[j]) swap(A, j, j + 1);
            j--;
        }
    }
}
private void swap(int[] A, int i, int j){
    int temp = A[i];
    A[i] = A[j];
    A[j] = temp;
}

Selection Sort

We find the smallest element in each pass and place it in the appropriate position to get the elements in ascending or descending order.
If we have n elements then it requires (n - 1) pass to sort.

In pass1, smallest element is searched between a[0] to a[n - 1] and swapped with a[0].
In pass2, smallest element is searched between a[1] to a[n - 1] and swapped with a[1].
In a similar way, the process is carried out n - 1 times.

Selection sort requires n - 1 pass to sort an array of n elements.
In each pass, we search for the smallest element from the search range and swap it with appropriate place.
In each pass we have n - k comparisons, where n is the number of elements and k is the pass number.
So, 1st pass requires n - 1 comparisons, kth pass requires n - k comparisons and the last pass requires 1 comparison.

Time Complexity
F(n) = (n - 1) + (n - 2) + (n - 3) + ... + 3 + 2 + 1 = n(n - 1)/2 = O(n^2)

public void sortIntegers(int[] A) {
    // Write your code here
    //corner case
    if(A == null || A.length <= 1) return;
    int len = A.length;
    for(int i = 0; i < len - 1; i++){
        //find the min
        int min = A[i];
         int minIndex = i;
        for(int j = i; j < len; j++){
            if(A[j] < min){
                min = A[j];
                minIndex = j;
            }
        }
        swap(A, i, minIndex);
    }
}

private void swap(int[] A, int i, int j){
    int temp = A[i];
    A[i] = A[j];
    A[j] = temp;
}

Merge Sort

We used the idea of divide and conquer. We divide the array into two parts, sort them and then merge them to get the elements in ascending or descending order.

Merge sort follows recursive algorithm. We divide the array into halves till the sub array has only 1 element. We need an extra temporary array of the same size as the input array for merging.

Stable (the relative position won't change)

Time Complexity
Divide: O(n)
Conquer: O(nlogn)
O(n) + O(nlogn) = O(nlogn)
Space Complexity
O(n)

One application of merge sort is external sort when the array cannot be fit in memory, doing merge in memory and flush sorted part into disk.

public void sortIntegers2(int[] A) {
    // Write your code here
    //corner case
    if(A == null || A.length <= 1) return;
    int[] helper = new int[A.length];
    mergeSort(A, helper, 0, A.length - 1);
    return;
}

private void mergeSort(int[] A, int[] helper, int left, int right){
    if(left == right) return;
    int mid = left + (right - left)/2;
    mergeSort(A, helper, left, mid);
    mergeSort(A, helper, mid + 1, right);
    merge(A, helper, left, right, mid);
}

private void merge(int[] A, int[] helper, int left, int right, int mid){
    for(int i = left; i <= right; i++){
        helper[i] = A[i];
    }
    int leftI = left;
    int rightI = mid + 1;
    while(leftI <= mid && rightI <= right){
        if(helper[leftI] < helper[rightI]){
            A[left++] = helper[leftI++];
        }else{
            A[left++] = helper[rightI++];
        }
    }
    while(leftI <= mid){
         A[left++] = helper[leftI++];
    }
}

Quick Sort

  1. Find pivot that divides the array into two halves.

  2. Quick sort the left half.

  3. Quick sort the right half.

Not stable

[0, l) < pivot
[l, r] to check
(r, length - 1 - 1] > pivot

All elements to the right of pivot must be greater than pivot. All elements to the left of pivot must be smaller than pivot.

Time Complexity
Average case: O(nlogn), every time partition the whole array into halves
Worst case: O(n^2) if every time choose the largest or smallest in the whole array, so n + n - 1 + n - 2 + .... + 2 + 1 = O(n^2)

So to avoid worst case, it's important to choose the pivot randomly.

Space Complexity
Depends on how many recursions
Best case: O(logn)
Worst case: O( n )

public void sortIntegers2(int[] A) {
    // Write your code here
    //corner case
    if(A == null || A.length <= 1) return;
    quickSort(A, 0, A.length - 1);
}

private void quickSort(int[] A, int left, int right){
    //base case
    if(left >= right) return;
    int pivotIndex = findPivot(A, left, right);
    quickSort(A, left, pivotIndex - 1);
    quickSort(A, pivotIndex + 1, right);
}

private int findPivot(int[] A, int left, int right){
    int pivotIndex = left + (int)Math.random()*(right - left + 1);
    int pivot = A[pivotIndex];
    swap(A, pivotIndex, right);
    int leftI = left;
    int rightI = right - 1;
    while(leftI <= rightI){
        if(A[leftI] < pivot) leftI++;
        else if(A[rightI] >= pivot) rightI--;
        else swap(A, leftI++, rightI--);
    }
    swap(A, leftI, right);
    return leftI;
}
private void swap(int[] A, int i, int j){
    int temp = A[i];
    A[i] = A[j];
    A[j] = temp;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值