排序算法

126 阅读2分钟

1. 选择排序

思路:每次选择一个最小(最大)的元素,放在第 i 个位置上(与位置 i 上的元素交换),i 的范围是[0,n-1]。

1.1 java

class Solution {
    //选择排序,选择最小的元素与位置i(i=[0,n-1])交换
    public int[] sortArray(int[] nums) {
        int n = nums.length;
        //选择n-1次,最后一次不用
        for(int i = 0; i < n - 1; ++ i) {
            int minIdx = i;//i~n-1中最小值的下标
            for(int j = i + 1; j < n; ++ j) {
                if(nums[j] < nums[minIdx]) {
                    minIdx = j;//更新最小值的下标
                }
            }
            swap(nums, i, minIdx);//元素交换
        }
        return nums;
    }

    public void swap(int[] nums, int x, int y) {
        int tmp = nums[x];
        nums[x] = nums[y];
        nums[y] = tmp;
    }
}

1.2 go

func sortArray(nums []int) []int {
    n := len(nums)
    for i := 0; i < n - 1; i ++ {
        minIdx := i
        for j := i + 1; j < n; j ++ {
            if nums[j] < nums[minIdx] {
                minIdx = j
            }
        }
        swap(nums, minIdx, i)
    }
    return nums
}

func swap(nums []int, x int, y int) {
    tmp := nums[x]
    nums[x] = nums[y]
    nums[y] = tmp
}

1.3 时空复杂度

时间复杂度:O(n^2)

空间复杂度:O(1)

2. 插入排序

思路:每一次将一个数字插入一个有序数组里,成为一个长度更长的数组,有限次操作后,数组整体有序。

2.1 java

class Solution {
    public int[] sortArray(int[] nums) {
        int n = nums.length;

        //找到nums[i]所在的位置
        for(int i = 0; i < n; i ++) {
            int tmp = nums[i];
            int j = i;
            //找到第一个不大于tmp(nums[i])的位置
            while(j > 0 && nums[j - 1] > tmp) {
                nums[j] = nums[j - 1];
                j --;
            }
            nums[j] = tmp;
        }
        return nums;
    }
}

2.2 go

func sortArray(nums []int) []int {
    n := len(nums)
    for i := 0; i < n; i ++ {
        tmp := nums[i]
        j := i
        for j > 0 && nums[j - 1] > tmp {
            nums[j] = nums[j - 1]
            j --
        }
        nums[j] = tmp
    }
    return nums
}

2.3 时空复杂度

时间复杂度:O(n^2)

空间复杂度:O(1)

3. 快速排序

3.1 java

class Solution {
    public int[] sortArray(int[] nums) {
        randomizedQuicker(nums, 0, nums.length - 1);
        return nums;
    }

    public void randomizedQuicker(int[] nums, int left, int right) {
        if(left < right) {
            int pos = randomizedPartition(nums, left, right);
            randomizedQuicker(nums, left, pos - 1);
            randomizedQuicker(nums, pos + 1, right);
        }
    }

    public int randomizedPartition(int[] nums, int left, int right) {
        //获取一个随机轴点
        int i = new Random().nextInt(right - left + 1) + left;
        swap(nums, i, right);
        return partition(nums, left, right);
    }

    public void swap(int[] nums, int x, int y) {
        int tmp = nums[x];
        nums[x] = nums[y];
        nums[y] = tmp;
    }

    public int partition(int[] nums, int left, int right) {
        int pivot = nums[right];
        int i = left - 1;
        for(int j = left; j < right; ++ j) {
            //[left, i]范围内的值都小于等于pivot
            if(nums[j] <= pivot) {
                i ++;
                swap(nums, i, j);
            }
        }
        swap(nums, i + 1, right);
        return i + 1;
    }
}

3.2 go

func sortArray(nums []int) []int {
    randomizedQuickSort(nums, 0, len(nums) - 1)
    return nums
}

func randomizedQuickSort(nums []int, left int, right int) {
    if left < right {
        pos := randomizedPartition(nums, left, right)
        randomizedQuickSort(nums, left, pos - 1)
        randomizedQuickSort(nums, pos + 1, right)
    }
}

func randomizedPartition(nums []int, left int, right int) int {
    i := rand.Intn(right - left + 1) + left
    swap(nums, i, right)
    return partition(nums, left, right)
}

func swap(nums []int, x int, y int) {
    tmp := nums[x]
    nums[x] = nums[y]
    nums[y] = tmp
}

func partition(nums []int, left int, right int) int {
    pivot := nums[right]
    i := left - 1
    for j := left; j < right; j ++ {
        if nums[j] <= pivot {
            i ++
            swap(nums, i, j)
        }
    }
    swap(nums, i + 1, right)
    return i + 1
}

3.3 时空复杂度

时间复杂度:最坏O(n^2),最好和平均时间复杂度为O(nlogn)

空间复杂度:最坏是O(n),最好和平均是O(logn)

4. 堆排序

4.1 java

class Solution {
    public int[] sortArray(int[] nums) {
        heapSort(nums);
        return nums;
    }

    public void heapSort(int[] nums) {
        int len = nums.length - 1;
        //建立大根堆
        buildMaxHeap(nums, len);
        for(int i = len; i >= 1; -- i) {
            swap(nums, i, 0);
            len --;
            maxHeapify(nums, 0, len);
        }
    }

    public void buildMaxHeap(int[] nums, int len) {
        //对所有的非叶子节点进行比较,自底向上
        for(int i = len/2; i >= 0; -- i){
            maxHeapify(nums, i, len);
        }
    }

    public void maxHeapify(int[] nums, int i, int len) {
        while( (i<<1) + 1 <= len ) {
            int lson = (i<<1) + 1;
            int rson = (i<<1) + 2;
            int large = i;
            if(lson <= len && nums[i] < nums[lson]) {
                large = lson;
            }
            if(rson <= len && nums[large] < nums[rson]) {
                large = rson;
            }
            if(large == i) break;
            swap(nums, i, large);
            i = large;
        }
    }

    public void swap(int[] nums, int x, int y) {
        int tmp = nums[x];
        nums[x] = nums[y];
        nums[y] = tmp;
    }
}

4.2 go

func sortArray(nums []int) []int {
    heapSort(nums)
    return nums
}

func heapSort(nums []int) {
    len := len(nums)-1
    buildMaxHep(nums, len)
    for i := len; i >= 1; i -- {
        swap(nums, i, 0)
        len --;
        maxHeapify(nums, 0, len);
    }
}

func buildMaxHep(nums []int, len int) {
    for i := len/2; i >= 0; i -- {
        maxHeapify(nums, i, len);
    }
}

func maxHeapify(nums []int, i int, len int) {
    for (i<<1) + 1 <= len {
        lson := (i<<1) + 1
        rson := (i<<1) + 2
        large := i
        if lson <= len && nums[i] < nums[lson] {
            large = lson
        }
        if rson <= len && nums[large] < nums[rson] {
            large = rson
        }
        if i == large {
            break
        }
        swap(nums, i, large)
        i = large
    }
}

func swap(nums []int, i int, j int) {
    tmp := nums[i]
    nums[i] = nums[j]
    nums[j] = tmp
} 

4.3 时空复杂度

时间复杂度:O(nlogn)

空间复杂度:O(1)

5. 归并排序

5.1 java

class Solution {
    int[] tmp;
    public int[] sortArray(int[] nums) {
        tmp = new int[nums.length];    
        mergeSort(nums, 0, nums.length - 1);
        return nums;
    }

    public void mergeSort(int[] nums, int left, int right) {
        if (left >= right) return;
        int mid = left + (right - left) / 2;
        mergeSort(nums, left, mid);
        mergeSort(nums, mid + 1, right);
        int idx = 0;
        int i = left, j = mid + 1;
        while(i <= mid && j <= right) {
            if(nums[i] < nums[j]) {
                tmp[idx++] = nums[i++];
            } else {
                tmp[idx++] = nums[j++];
            }
        }
        while(i<=mid){
            tmp[idx++] = nums[i++];
        }
        while(j<=right) {
            tmp[idx++] = nums[j++];
        }
        idx = 0;
        for(int k = left; k <= right; ++ k) {
            nums[k] = tmp[idx++];
        }
    }
}

5.2 go

var tmp []int

func sortArray(nums []int) []int {
    tmp = make([]int, len(nums))
    mergeSort(nums, 0, len(nums)-1)
    return nums
}

func mergeSort(nums []int, left int, right int) {
    if left >= right {
        return
    }

    mid := left + (right-left)/2
    mergeSort(nums, left, mid)
    mergeSort(nums, mid+1, right)

    i := left
    j := mid + 1
    idx := 0
    for i <= mid && j <= right {
        if nums[i] < nums[j] {
            tmp[idx] = nums[i]
            idx++
            i ++
        } else {
            tmp[idx] = nums[j]
            idx ++
            j ++
        }
    }
    for i <= mid {
        tmp[idx] = nums[i]
        idx ++
        i ++
    }

    for j <= right {
        tmp[idx] = nums[j]
        idx ++
        j ++
    }

    idx = 0
    for k := left; k <= right; k ++ {
        nums[k] = tmp[idx]
        idx ++
    }
}

5.3 时空复杂度

时间复杂度:O(nlogn)

空间复杂度:O(n)

6. 冒泡排序

6.1 java

class Solution {
    public int[] sortArray(int[] nums) {
        int n = nums.length;
        for(int i = 0; i < n; ++ i){
            for(int j = 0; j < n-i-1; ++ j) {
                if(nums[j] > nums[j + 1]) {
                    swap(nums, j, j+1);
                }
            }
        }
        return nums;
    }

    public void swap(int[] nums, int x, int y) {
        int tmp = nums[x];
        nums[x] = nums[y];
        nums[y] = tmp;
    }
}

6.2 go

func sortArray(nums []int) []int {
    n := len(nums)

    for i := 0; i < n; i ++ {
        for j := 0; j < n-i-1; j ++ {
            if nums[j] > nums[j+1] {
                swap(nums, j, j+1)
            }
        }
    }
    return nums
}

func swap(nums []int, x int, y int) {
    tmp := nums[x]
    nums[x] = nums[y]
    nums[y] = tmp
}

6.3 时空复杂度

时间复杂度:O(n^2)

空间复杂度:O(1)

7. 计数排序

7.1 java

class Solution {
    public int[] sortArray(int[] nums) {
        int min = nums[0], max = nums[0];
        int n = nums.length;
        for(int i = 0; i < n; ++ i) {
            min = Math.min(min, nums[i]);
            max = Math.max(max, nums[i]);
        }
        int len = max - min + 1;
        int[] cnt = new int[len];
        for(int num : nums) {
            cnt[num-min] ++;
        }
        int idx = 0;
        for(int i = 0; i < len; ++ i) {
            for(int j = cnt[i]; j > 0; j--) {
                nums[idx++] = i + min;
            }
        }
        return nums;
    }
}

7.2 go

func Max(a,b int) int {
    if a>b{
        return a
    }
    return b
}
func Min(a,b int) int {
    if a>b{
        return b
    }
    return a
}
func sortArray(nums []int) []int {
    maxs:=nums[0]
    mins:=nums[0]
    for _,v := range(nums){
        maxs=Max(maxs,v)
        mins=Min(mins,v)
    }
    cnts:=make([]int,maxs-mins+1)
    for _,v :=range(nums){
        cnts[v-mins]+=1
    }
    cnt:=0
    for i,j :=range(cnts){
        for ;j>0;j--{
            nums[cnt]=i+mins
            cnt+=1
        }
    }
    return nums
}

7.3 时空复杂度

时间复杂度:O(n) n表示最小值到最大值的取值范围

空间复杂度:O(n) n表示最小值到最大值的取值范围