LeetCode_Sorting_912. Sort an Array 排序数组【快速排序,堆排序,归并排序】【java】【中等】

目录

一,题目描述

英文描述

中文描述

示例与说明

二,解题思路

快速排序

堆排序

归并排序

三,AC代码

Java

快速排序(随机哨兵)

堆排序

归并排序

四,解题过程

第一博

第二搏

第三搏


一,题目描述

英文描述

Given an array of integers nums, sort the array in ascending order.

中文描述

给你一个整数数组 nums,请你将该数组升序排列。

示例与说明

提示:

  1. 1 <= nums.length <= 50000
  2. -50000 <= nums[i] <= 50000

二,解题思路

参考@力扣官方题解【排序数组】

快速排序

普通的快速排序(默认将哨兵设置为第一个或者最后一个元素)会超时,这里采用官方题解中的方法,设置随机哨兵pivot。

int index = (int) Math.random() * (l - r) + l;// 生成[l, r)之间的随机数
int pivot = nums[index];

堆排序

将数组中的元素一个个添加入堆中,执行siftUp操作;

将堆顶元素与堆中末尾元素调换,边界减一,自上而下调整堆;

当堆中元素为空,数组完成排序。

归并排序

经典的递归思想。

将数组拆成两部分,这两部分均调用MergeSort方法,可以看作已经排好序,接下来只需要进行合并有序数组的操作。

这里的空间复杂度为O(N),因为合并有序数组时,额外创建了一块区域,用来存放合并的结果,最后将结果拷贝至原数组中。(若直接在原数组中进行合并操作,过程较为复杂)

三,AC代码

Java

快速排序(随机哨兵)

class Solution {
    public void swap (int[] nums, int a, int b) {
        int tem = nums[a];
        nums[a] = nums[b];
        nums[b] = tem;
    }
    public static void quickSort(int[] array, int left, int right) {
        if (right - left < 2) return;
        int index = partation(array, left, right);
        quickSort(array, left, index);
        quickSort(array, index, right);
    }
    public static int partation(int[] array, int left, int right) {
        int index = (int) (Math.random() * (right - left) + left);// !!!获得随机哨兵位置
        System.out.println("#" + index);
        int pivot = array[index];// 记录哨兵值
        swap(array, left, index);// 将哨兵与待排序区间首个元素交换
        index = left;
        for(int i = left + 1; i < right; i++) {
            if (array[i] < pivot) {
                swap(array, ++index, i);
            }
        }
        swap(array, left, index);// 将哨兵与已分区区间的最后一个元素交换
        return index;
    }
    public int[] sortArray(int[] nums) {
        quickSort(nums, 0, nums.length);// 
        return nums;
    }
}

堆排序

class Solution {
    public void swap (int[] nums, int a, int b) {
        int tem = nums[a];
        nums[a] = nums[b];
        nums[b] = tem;
    }
    public void siftUp (int[] nums, int index) {
        int fatherIndex = (index - 1) / 2;
        while (fatherIndex >= 0 && nums[index] > nums[fatherIndex]) {
            swap(nums, fatherIndex, index);
            index = fatherIndex;
            fatherIndex = (index - 1) / 2;
        }
    }
    public void siftDown (int[] nums, int index, int border) {
        int childIndex = index * 2 + 1;
        while (childIndex < border) {
            if (childIndex + 1 < border && nums[childIndex + 1] > nums[childIndex]) {
                childIndex++;
            }
            if (nums[index] > nums[childIndex]) break;// 该节点大于任意子节点
            swap(nums, index, childIndex);
            index = childIndex;
            childIndex = index * 2 + 1;
        }
    }
    public void heapSort(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            siftUp(nums, i);// 构建大根堆
        }
        for (int i = nums.length - 1; i > 0; i--) {
            swap(nums, 0, i);// 将堆顶元素调整到数组末尾
            siftDown(nums, 0, i);// 自上向下调整堆
        }
    }

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

归并排序

class Solution {
    public static int[] merge(int[] left, int[] right) {
        int[] result = new int[left.length + right.length];
        for (int i = 0, j = 0, index = 0; index < left.length + right.length; index++) {
            if (i >= left.length) {
                result[index] = right[j++];
            } else if (j >= right.length) {
                result[index] = left[i++];
            } else if (left[i] < right[j]) {
                result[index] = left[i++];
            } else {
                result[index] = right[j++];
            }
        }
        return result;
    }
    public static int[] mergeSort(int[] array, int l, int r) {
        if (r - l < 2) return array;
        int mid = (l + r) / 2;
        int[] left = Arrays.copyOfRange(array, l, mid);
        int[] right = Arrays.copyOfRange(array, mid, r);

        return merge(mergeSort(left, 0, left.length), mergeSort(right, 0, right.length));
    }

    public int[] sortArray(int[] nums) {
        mergeSort(nums, 0, nums.length);            // !!!注意边界
        return nums;
    }
}

四,解题过程

第一博

设置随机哨兵的快速排序(细节调了将近50min。。。)

第二搏

堆排序,之前实现过类似的结构,这里比较轻松

第三搏

归并排序,细节细节!边界一定要搞清楚

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值