算法学习100天——8 快速排序2

题目地址(912. 排序数组)

https://leetcode-cn.com/problems/sort-an-array/

题目描述

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

示例 1:
输入:nums = [5,2,3,1]
输出:[1,2,3,5]

示例 2:
输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]

提示:
1 <= nums.length <= 5 * 104
-5 * 104 <= nums[i] <= 5 * 104

代码

Java Code:

/**
 * 快排的过程
 * 1. 递归出口
 * 2. 找基准点(随机基准点),并将基准点与数组首地址元素交换(或者尾地址的)
 * 3. 根据基准点的值,将数组元素分为 小于等于 + 大于 两部分,并记录分界线
 * 4. 将尾部基准点交换至分界线处的元素
 * 5. 将除开基准值的两两端数组继续执行同样操作
 * 最后得到一个升序数组
 
 ** 几个要注意的点:
 * 1. 基准值可以不随机,但是遇到数组已经是升序或者降序的情况,时间复杂度度可能为O(N²)
 * 2. 分界线处的交换要注意基准值的位置,避免二次打乱已排好的顺序
 * 3. 递归必须要有出口。。。。
 */
    
class Solution {
    public int[] sortArray(int[] nums) {
        fastSort(nums, 0,nums.length - 1);
        return nums;
    }

    private void fastSort(int[] nums, int left, int right){
        // 递归出口
        if(left >= right){
            return;
        }

        // 随机一个基准点,并交换到数组首位置
        generateRandomPosition(nums, left, right);
        // 遍历数组,根据基准数排列
        int pos = sort(nums, left, right);
        // 基准数两边分别递归
        fastSort(nums, left, pos - 1);
        fastSort(nums, pos + 1, right);
    }

    private void generateRandomPosition(int[] nums, int left, int right){
        int index =left + new Random().nextInt(right - left + 1);
        swap(nums, index, right);
    }

    private int sort(int[] nums, int left, int right){
        int i = left;
        int pos = i;
        // 双指针法,基于基准值对数组元素分类
        while(i < right){
            if(nums[i] <= nums[right]){
                swap(nums, pos, i);
                pos++;
            }
            i++;
        }
        // 将数组首位与 基准数应该在的位置值交换
        swap(nums, pos, right);

        // 返回基准数,用于分段
        return pos;
    }

    private void swap(int[] nums, int left, int right){
        int temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
    }
}

结果

快排时间复杂度不稳定 ,数组排序还是归并好用一些

posted @ 2022-03-05 23:27  浪漫主义程序员  阅读(29)  评论(0编辑  收藏  举报