一、题目描述

给你一个整数数组 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 <= 50000
-50000 <= nums[i] <= 50000

二、解题思路

快速排序的主要思想是通过划分将待排序的序列分成前后两部分,其中前一部分的数据都比后一部分的数据要小,然后再递归调用函数对两部分的序列分别进行快速排序,以此使整个序列达到有序。

我们定义函数 randomized_quicksort(nums, left, right) 为对 nums 数组里[left,right]的部分进行排序,每次先调用 randomized_partition 函数对 nums 数组里 [left,right] 的部分进行划分,并返回分界值的下标 pos,然后按上述将的递归调用

randomized_quicksort(nums, left, pos - 1)

和 randomized_quicksort(nums, pos + 1, right) 即可。

那么核心就是划分函数的实现了,划分函数一开始需要确定一个分界值(我们称之为主元 pivot),然后再进行划分。而主元的选取有很多种方式,这里我们采用随机的方式,对当前划分区间 [left,right] 里的数等概率随机一个作为我们的主元,再将主元放到区间末尾,进行划分。

整个划分函数 partition 主要涉及两个指针 i 和 j,一开始 i = j = left。我们需要实时维护两个指针使得任意时候,对于任意数组下标 k,我们有如下条件成立:

left≤k≤i-1 时,nums[k]≤pivot。

i≤k≤j−1 时,nums[k]>pivot。

k==right 时,nums[k]=pivot。

我们每次移动指针 j ,如果 nums[j]>pivot,我们只需要继续移动指针 j ,即能使上述三个条件成立,否则我们需要交换 nums[i] 和nums[j],然后将指针 i 加一,再移动指针 j 才能使得三个条件成立。

当 j 移动到right−1 时结束循环,此时我们可以由上述三个条件知道 [left,i) 的数都小于等于主元 pivot,[i,right-1]的数都大于主元 pivot,那么我们只要交换nums[i] 和nums[right] ,即能使得 [left,i) 区间的数都小于[i,right] 区间的数,完成一次划分,且分界值下标为i,返回即可。

如下的动图展示了一次划分的过程,刚开始随机选了 4作为主元,与末尾元素交换后开始划分:

三、代码

java

public class Solution {public int[] quickSort(int[] nums,int low,int high) {if(low>=high){return nums;}int i=low,j=high,pivot=nums[high];while(i<j){while(i<j&&nums[i]<pivot){//从左往右找大于中枢的i++;}nums[j]=nums[i];while(i<j&&nums[j]>=pivot){//从右往左找小于中枢的j--;}nums[i]=nums[j];}nums[i]=pivot;quickSort(nums,low,i-1);quickSort(nums,i+1,high);return nums;}public int[] sortArray(int[] nums) {return quickSort(nums,0,nums.length-1);}public static void main(String[] args) {int[] nums={1,2,5,4,3};Solution solution=new Solution();int[] rs=solution.sortArray(nums);for(int i=0;i<rs.length;i++){System.out.println(rs[i]);}}
}

C++

class Solution {int partition(vector<int>& nums, int left, int right) {int pivot = nums[right];int i = left;for (int j = left; j <= right - 1; ++j) {if (nums[j] <= pivot) {swap(nums[i++], nums[j]);}}swap(nums[i], nums[right]);return i;}int randomized_partition(vector<int>& nums, int l, int r) {int i = rand() % (r - l + 1) + l; // 随机选一个作为我们的主元swap(nums[r], nums[i]);return partition(nums, l, r);}void randomized_quicksort(vector<int>& nums, int l, int r) {if (l < r) {int pos = randomized_partition(nums, l, r);randomized_quicksort(nums, l, pos - 1);randomized_quicksort(nums, pos + 1, r);}}
public:vector<int> sortArray(vector<int>& nums) {randomized_quicksort(nums, 0, (int)nums.size() - 1);return nums;}
};

四、复杂度分析

时间复杂度:基于随机选取主元的快速排序时间复杂度为期望O(nlogn),其中 n 为数组的长度。详细证明过程可以见《算法导论》第七章,这里不再大篇幅赘述。

空间复杂度:O(h),其中 h 为快速排序递归调用的层数。我们需要额外的 O(h) 的递归调用的栈空间,由于划分的结果不同导致了快速排序递归调用的层数也会不同,最坏情况下需 O(n) 的空间,最优情况下每次都平衡,此时整个递归树高度为 logn,空间复杂度为 O(logn)。

Leetcode No.912 排序数组(快速排序)相关推荐

  1. LeetCode:912. 排序数组

    给你一个整数数组 nums,请你将该数组升序排列. 示例 1: 输入:nums = [5,2,3,1] 输出:[1,2,3,5] 示例 2: 输入:nums = [5,1,1,2,0,0] 输出:[0 ...

  2. LeetCode 912. 排序数组(Java)

    912. 排序数组 你一个整数数组 nums,请你将该数组升序排列. 示例 1: 输入:nums = [5,2,3,1] 输出:[1,2,3,5] 提示: 1 <= nums.length &l ...

  3. Leetcode 912.排序数组(Sort an Array)

    Leetcode 912.排序数组 1 题目描述(Leetcode题目链接)   给定一个整数数组 nums,将该数组升序排列. 输入:[5,2,3,1] 输出:[1,2,3,5] 输入:[5,1,1 ...

  4. LeetCode 912. 排序数组【模板题】

    912. 排序数组 [快排] class Solution {// 快速排序 7:32 13void quickSort(int[] nums, int l, int r){if(l >= r) ...

  5. Leetcode.912 排序数组

    题目链接 Leetcode.912 排序数组 mid 题目描述 给你一个整数数组 n u m s nums nums,请你将该数组升序排列. 示例 1: 输入:nums = [5,2,3,1] 输出: ...

  6. C++描述 LeetCode 26. 删除排序数组中的重复项

    C++描述 LeetCode 26. 删除排序数组中的重复项   大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博主目前仅在CSDN中写博客 ...

  7. LeetCode 912. 排序数组(10种排序)

    文章目录 1. 题目 2. 解题 2.1 插入排序 2.2 冒泡排序 2.3 选择排序 2.4 希尔排序 2.5 归并排序 2.6 快速排序 2.7 堆排序 2.8 计数排序 2.9 桶排序 2.10 ...

  8. LeetCode[912]排序数组

    难度:Medium 题目: 给你一个整数数组 nums,请你将该数组升序排列. 示例 1: 输入:nums = [5,2,3,1] 输出:[1,2,3,5] 示例 2: 输入:nums = [5,1, ...

  9. LeetCode 80. 删除排序数组中的重复项 II

    1. 题目 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完 ...

最新文章

  1. emwin读取sd图片_262.3MB/S读取速率,雷克沙1667X这回谁还敢吐槽
  2. locust自己调试
  3. 为什么说“人生苦短,我用Python”?为什么Python这么火?
  4. oracle逻辑结构包含,在Oracle中,逻辑结构由哪几个部分组成?
  5. 如何更好的解决问题 : The puzzle of die
  6. Android内存优化2—使用软引用和弱引用
  7. vue-:class的几种使用方式
  8. 聊一聊Load Average
  9. Could not load driverClass “com.mysql.jdbc.Driver“
  10. dockerfile拉取私库镜像_还在用Alpine作为你Docker的Python开发基础镜像?其实Ubuntu更好一点...
  11. “王者对战”之 MySQL 8 vs PostgreSQL 10
  12. 一场由fork引发的超时,让我们重新探讨了Redis的抖动问题
  13. 九零后女孩币圈变形记
  14. 零配置构建工具:parcel
  15. 唐诗辑注 —— 辛夷坞、南园十三首、问六十九
  16. 解决windows写Django项目在templates中的html文件中引入外部css,js不成功的方法
  17. php官网软件下载,php下载_php官方下载_3DM软件
  18. minitab学习系列(2)--CPK、PPK案例解析
  19. AM335X-IO输入总是读不到输入电平——8
  20. 飞书深诺在港上市招股书再失效:毛利率较高,遭完美世界提前减持

热门文章

  1. 2020Java书单推荐
  2. C语言求1+1/2+.....1/n的和
  3. 循环结构,for循环重要!!!
  4. 制定项目计划,确保团队协同效率
  5. 802.1x准入技术
  6. 23 种设计模式详解
  7. 奈奎斯特定理和香农第二定理
  8. python自动测试h_软件自动化测试资源列表
  9. 中国惠普前总裁 孙振耀的毕生经验之谈
  10. 集合与映射--确界与连续性公理