912. Sort an Array排序复习 快速排序,选择排序,插入排序,归并排序,堆排序

本文主要是介绍912. Sort an Array排序复习 快速排序,选择排序,插入排序,归并排序,堆排序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

快速排序

选择排序 

插入排序

归并排序

堆排序

总结


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

Example 1:

Input: nums = [5,2,3,1]
Output: [1,2,3,5]

Example 2:

Input: nums = [5,1,1,2,0,0]
Output: [0,0,1,1,2,5]

Constraints:

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

题目链接: Loading...

快速排序

class Solution {
public:void quicksort(vector<int>&nums,int left,int right){if(left>=right)//此处应该是大于等于,等于的时候就可以停止了{return ;}int i=left,j=right,key=nums[left];while(i<j){while(i<j&&nums[j]>=key){//选出来的nums[j] 小于 keyj--;}nums[i]=nums[j];while(i<j&&nums[i]<=key)//选出来的nums[i] 大于 key{i++;}nums[j]=nums[i];}nums[i]=key;quicksort(nums,left,i-1);quicksort(nums,i+1,right);}vector<int> sortArray(vector<int>& nums) {quicksort(nums,0,nums.size()-1);return nums;}
};

快速排序是不稳定的,为什么呢?

经过第一次sort后,对于j,j=5就停止了,对于i,i一直++到5。

这样赋值后,红色的9跑到黑色的9后面了。 

有的例子就刚好不会变,下面这种就不会变化。

选择排序 

是想复习一下,但是选择排序复杂度比较高,过不了。这些排序的复杂度表

void selectSort(vector<int>&nums){int len=nums.size();int index=0;for(int i=0;i<len;i++){index=i;for(int j=i+1;j<len;j++){if(nums[j]<nums[index]){index=j;}}int tmp=nums[i];nums[i]=nums[index];nums[index]=tmp;}}

插入排序

也是超时,原理很简单,在从小到大的排序方法中,就是  左边有序序列,新来一个值newvalue,就和左边有序序列比较,只要比我,我就往右边挪位置,nums[j+1]=nums[j]。

void insertSort(vector<int>& nums){int len=nums.size(),tmp=0,i=0,j=0;for(i=1;i<len;i++){tmp=nums[i];for(j=i-1;j>=0&&tmp<nums[j];j--){nums[j+1]=nums[j];//nums[j]小于 tmp,往后挪位置}nums[j+1]=tmp;//j退出时候,要么j=-1,或者 nums[j]< tmp,那你tmp只能放在 j+1的位置上}}

归并排序

这道题在归并排序上真是给我好好上了一课,之前写的归并排序没有问题,但是有一些额外的空间浪费和时间开销。就是我全行注释那行,如果每次都是按照nums的真实长度来初始化tmp,会浪费时间和空间,这题LeetCode会超时。刚开始我百思不得其解,后来发现是这个问题,真是学习了。我之前写的归并代码:随手写写之归并排序

    void mergeArray(vector<int>& nums,int start,int mid,int last){vector<int> tmp(last-start+1,0);// vector<int> tmp(nums.size(),0);这一点真的很棒,考虑数组元素多的时候,这样初始化很浪费时间,会超时,这点leetcode给我上了一课。int i=start,j=mid+1,k=0;//k记录start位置,tmp从哪个下标开始while(i<=mid&&j<=last){if(nums[i]<nums[j]){tmp[k++]=nums[i++];}else{tmp[k++]=nums[j++];}}while(i<=mid){tmp[k++]=nums[i++];}while(j<=last){tmp[k++]=nums[j++];}for(int t=start;t<=last;t++){nums[t]=tmp[t-start];}}void mergeSort(vector<int>& nums,int start,int last){if(start<last){int mid=(start+last)/2;mergeSort(nums,start,mid);mergeSort(nums,mid+1,last);mergeArray(nums,start,mid,last);}}

  

堆排序

堆排序(这篇博客说的挺好的排序六 堆排序)是使用大根堆(父节点不小于子节点,为啥从下往上调整呢,看个例子

把3和1调完之后, 根节点还要调整(因为4是最大的,4还要和根节点调整,导致根节点的值换了2次,从下往上调整,根节点只需要调整一次就行了,这样从下往上调整,所有非叶子节点调整一次,绝对就是对的了,不用考虑有的节点是不是还要调整一次),一个节点就可能重复调整,不止一次。从下往上调整,省去了父节点二次调整,简单省事了,不用考虑二次调整了。

这个例子第一次的调整构造初始堆过程如下图:

上面这个例子层数有点少,2种遍历都是调整3次,但是对于一个节点,既是父节点又是子节点,它的子节点还有子节点 ,步骤就上来了,比如下图的数字4

void heapAdjust(vector <int> & arr, int parent,int N){int largest = parent;int child=2*parent+1;while(child<N)//N代表整个数组的元素个数,下标从0开始,child必须小于N{if(arr[child]>arr[largest]){largest=child;}if(child+1<N&&arr[child+1]>arr[largest]){largest=child+1;child++;//更新child的值}swap(arr[parent],arr[largest]);//交换parent=largest;// parent=child;在没有child大于parent的时候,largest还是parent,child是2*parent+1,所以不能这么写child=2*child+1;//child根据child值翻倍,这样如果么有需要更新的,parent一直不变,child一直增大会退出}}void heapSort(vector<int>& nums){for(int i = nums.size()/2; i >= 0; i--){//从最后一个非叶子节点开始调整heapAdjust(nums,i,nums.size());}for(int i = nums.size()-1; i >= 0; i--){swap(nums[0] , nums[i]);//下标0存放的是调整后最大值,交换后放到下标 i(当前未排序的最后位置)heapAdjust(nums,0,i);//i表示调整的元素个数,i从 size()-1  开始}}

堆排序是不稳定的,看个图,原先的数组顺序是 1 2 2,调整之后 1 2 2,黄框是排序一次后的堆结构。

 

总结

对于这道题,我把所有排序方法都汇总在一起了

class Solution {
public:
void quickSort(vector<int>&nums,int left,int right){if(left>right){return ;}int i=left,j=right,key=nums[left];while(i<j){while(i<j&&nums[j]>=key){//选出来的nums[j] 小于 keyj--;}nums[i]=nums[j];while(i<j&&nums[i]<=key)//选出来的nums[i] 大于 key{i++;}nums[j]=nums[i];}nums[i]=key;quickSort(nums,left,i-1);quickSort(nums,i+1,right);}void selectSort(vector<int>&nums){int len=nums.size();int index=0;for(int i=0;i<len;i++){index=i;for(int j=i+1;j<len;j++){if(nums[j]<nums[index]){index=j;}}int tmp=nums[i];nums[i]=nums[index];nums[index]=tmp;}}void insertSort(vector<int>& nums){int len=nums.size(),tmp=0,i=0,j=0;for(i=1;i<len;i++){tmp=nums[i];for(j=i-1;j>=0&&tmp<nums[j];j--){nums[j+1]=nums[j];//nums[j]小于 tmp,往后挪位置}nums[j+1]=tmp;//j退出时候,要么j=-1,或者 nums[j]< tmp,那你tmp只能放在 j+1的位置上}}void mergeArray(vector<int>& nums,int start,int mid,int last){vector<int> tmp(last-start+1,0);// vector<int> tmp(nums.size(),0);这一点真的很棒,考虑数组元素多的时候,这样初始化很浪费时间,会超时,这点leetcode给我上了一课。int i=start,j=mid+1,k=0;//k记录start位置,tmp从哪个下标开始while(i<=mid&&j<=last){if(nums[i]<nums[j]){tmp[k++]=nums[i++];}else{tmp[k++]=nums[j++];}}while(i<=mid){tmp[k++]=nums[i++];}while(j<=last){tmp[k++]=nums[j++];}for(int t=start;t<=last;t++){nums[t]=tmp[t-start];}}void mergeSort(vector<int>& nums,int start,int last){if(start<last){int mid=(start+last)/2;mergeSort(nums,start,mid);mergeSort(nums,mid+1,last);mergeArray(nums,start,mid,last);}}void heapAdjust(vector <int> & arr, int parent,int N){int largest = parent;int child=2*parent+1;while(child<N)//N代表整个数组的元素个数,下标从0开始,child必须小于N{if(arr[child]>arr[largest]){largest=child;}if(child+1<N&&arr[child+1]>arr[largest]){largest=child+1;child++;//更新child的值}swap(arr[parent],arr[largest]);//交换parent=largest;// parent=child;在没有child大于parent的时候,largest还是parent,child是2*parent+1,所以不能这么写child=2*child+1;}// int left = 2*parent+1;// int right = 2*parent+2;// if(left < N && arr[left] > arr[largest])//     largest = left;// if(right < N && arr[right] > arr[largest])//     largest = right;// if(largest != parent){//     swap(arr[parent], arr[largest]);//     heapAdjust(arr,largest,N);// }}void heapSort(vector<int>& nums){for(int i = nums.size()/2; i >= 0; i--){//从最后一个非叶子节点开始调整heapAdjust(nums,i,nums.size());}for(auto it:nums){cout<<it<<endl;}for(int i = nums.size()-1; i >= 0; i--){swap(nums[0] , nums[i]);//下标0存放的是调整后最大值,交换后放到下标 i(当前未排序的最后位置)heapAdjust(nums,0,i);//i表示调整的元素个数,i从 size()-1  开始}}vector<int> sortArray(vector<int>& nums) {// quickSort(nums,0,nums.size()-1);// selectSort(nums);// insertSort(nums);// mergeSort(nums,0,nums.size()-1);heapSort(nums);return nums;}};

复杂度汇总 

 

这篇关于912. Sort an Array排序复习 快速排序,选择排序,插入排序,归并排序,堆排序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/289036

相关文章

Python 中 requests 与 aiohttp 在实际项目中的选择策略详解

《Python中requests与aiohttp在实际项目中的选择策略详解》本文主要介绍了Python爬虫开发中常用的两个库requests和aiohttp的使用方法及其区别,通过实际项目案... 目录一、requests 库二、aiohttp 库三、requests 和 aiohttp 的比较四、requ

Python中lambda排序的六种方法

《Python中lambda排序的六种方法》本文主要介绍了Python中使用lambda函数进行排序的六种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1.对单个变量进行排序2. 对多个变量进行排序3. 降序排列4. 单独降序1.对单个变量进行排序

shell脚本快速检查192.168.1网段ip是否在用的方法

《shell脚本快速检查192.168.1网段ip是否在用的方法》该Shell脚本通过并发ping命令检查192.168.1网段中哪些IP地址正在使用,脚本定义了网络段、超时时间和并行扫描数量,并使用... 目录脚本:检查 192.168.1 网段 IP 是否在用脚本说明使用方法示例输出优化建议总结检查 1

el-select下拉选择缓存的实现

《el-select下拉选择缓存的实现》本文主要介绍了在使用el-select实现下拉选择缓存时遇到的问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录项目场景:问题描述解决方案:项目场景:从左侧列表中选取字段填入右侧下拉多选框,用户可以对右侧

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

Rust中的Option枚举快速入门教程

《Rust中的Option枚举快速入门教程》Rust中的Option枚举用于表示可能不存在的值,提供了多种方法来处理这些值,避免了空指针异常,文章介绍了Option的定义、常见方法、使用场景以及注意事... 目录引言Option介绍Option的常见方法Option使用场景场景一:函数返回可能不存在的值场景

在Java中实现堆排序的步骤详解

《在Java中实现堆排序的步骤详解》堆排序是一种基于堆数据结构的排序算法,堆是一种特殊的完全二叉树,堆排序利用堆的性质通过一系列操作将数组元素按升序或降序排列,本文给大家介绍了如何在Java中实现堆排... 目录引言一、堆排序的基本原理二、堆排序的实现步骤三、堆排序的时间复杂度和空间复杂度四、堆排序的工作流

如何选择适合孤独症兄妹的学校?

在探索适合孤独症儿童教育的道路上,每一位家长都面临着前所未有的挑战与抉择。当这份责任落在拥有孤独症兄妹的家庭肩上时,选择一所能够同时满足两个孩子特殊需求的学校,更显得尤为关键。本文将探讨如何为这样的家庭做出明智的选择,并介绍星贝育园自闭症儿童寄宿制学校作为一个值得考虑的选项。 理解孤独症儿童的独特性 孤独症,这一复杂的神经发育障碍,影响着儿童的社交互动、沟通能力以及行为模式。对于拥有孤独症兄

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig