【cpp】快速排序优化

标题:【cpp】快速排序

@水墨不写bug


正文开始:

 快速排序的局限性:

虽然快速排序是一种高效的排序算法,但也存在一些局限性:

  1. 最坏情况下的时间复杂度:如果选择的基准元素不合适,或者数组中存在大量重复的元素,快速排序的时间复杂度可能退化为O(n^2)。这种情况发生在每次划分之后,基准元素都是当前子数组中的最小或最大元素。

  2. 对于小规模数据的排序效果较差:当数组规模较小时,例如只有几个元素,快速排序的性能可能不如其他简单的排序算法,如插入排序或选择排序。

  3. 对于有序数组的排序效果较差:如果待排序的数组已经接近有序,快速排序的性能会下降。因为在划分过程中,基准元素的选择可能会导致子数组的不平衡,使得算法执行的时间增加。

  4. 快速排序是一种不稳定的排序算法:当原始数组中存在相等元素时,算法执行过程中可能会改变它们的相对顺序。

        如何优化重复元素的问题,以免快排的时间复杂度退化为O(N^2)?

        通过下面这一问题,我们或许会得到一些启发。 

(一)颜色分类(leetcode)

        给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

        我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

        必须在不使用库内置的 sort 函数的情况下解决这个问题。

示例 1:

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

示例 2:

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

提示:

  • n == nums.length
  • 1 <= n <= 300
  • nums[i] 为 01 或 2

进阶:

  • 你能想出一个仅使用常数空间的一趟扫描算法吗?

        颜色分类思想:

        定义三个指针(left,cur,right):

        在排序过程中,这三个指针(left,cur,right),将数组分为四个部分,接下来希望你拿出纸笔跟我一起画一下:

        四个部分:

        一:【0,left】 

        二:【left+1,cur-1】 

        三:【cur,right-1】 

        四:【right,len-1】  

主体思路是:

        cur向后遍历,将小于1的元素放在left左边,等于1的元素不变位置,大于1的元素放在right的右边。

        需要注意的细节是,对于(nums[cur] == 0 )由于left是右闭区间,其指向的元素满足要求,所以要先自增再交换;交换之后cur++向后遍历。

        对于(nums[cur] == 1)cur直接向后遍历;

        对于(nums[cur] == 2)由于left是左闭区间,其指向的元素满足要求,所以要先自减再交换;right在交换之前指向的元素本身就是未遍历的元素,所以交换之后不需要cur自增,直接判断cur交换得到的未遍历的元素即可。

        

class Solution {
public:void sortColors(vector<int>& nums) {int n = nums.size();for(int left = -1,right = n,cur = 0;cur < right;){if(nums[cur] == 0) swap(nums[++left],nums[cur++]);else if(nums[cur] == 1) cur++;else swap(nums[--right],nums[cur]);}}
};

(二)排序数组(leetcode)

        给你一个整数数组 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 * 10^4
  • -5 * 10^4 <= nums[i] <= 5 * 10^4

        根据颜色分类的主体思想,如果用颜色分类来优化快排,那么这时再出现大量重复元素,就可以一次将他们排好序,不会再出现 在每次划分之后,基准元素都是当前子数组中的最小或最大元素的情况。

class Solution {
public:vector<int> sortArray(vector<int>& nums) {srand(time(NULL));qsort(nums,0,nums.size()-1);return nums;}void qsort(vector<int>& nums,int l,int r){//递归出口if(l >= r) return;//数组分三块int key = GetRandom(nums,l,r);int cur = l,left = l-1,right = r+1;while(cur < right){if(nums[cur] < key) swap(nums[++left],nums[cur++]);else if(nums[cur] == key) cur++;else swap(nums[--right],nums[cur]); }//递归排序子区间qsort(nums,l,left);qsort(nums,right,r);}int GetRandom(vector<int>& nums,int left,int right){int r = rand();return nums[ r % ( right - left + 1 ) + left];}
};

代码理解: 

         上述代码是用C++实现的快速排序算法,用于对一个整数数组进行排序。sortArray函数接收一个输入向量nums,并使用qsort函数对其进行排序。

1.函数参数

qsort函数是一个递归函数,用于执行快速排序算法。它接收三个参数:输入向量nums、左边界索引l和右边界索引r

2.递归出口的定义

        函数有一个基本情况,即如果左边界索引大于或等于右边界索引,那么只有一个元素或没有元素需要排序,所以函数返回。

3.key的选取

        使用GetRandom函数选择一个随机的轴元素(key),该函数在当前分区的范围内生成一个随机的索引。

4.递归主体

        然后,函数将数组分为三部分:小于轴元素(key)的元素、等于轴元素(key)的元素和大于轴元素(key)的元素。它使用三个指针:curleftright

cur指针从左边界索引开始,向右边界索引移动,并相应地交换元素。如果当前元素小于轴元素,则将其与left指针处的元素交换,并同时递增这两个指针。如果当前元素等于轴元素,则递增cur指针。如果当前元素大于轴元素,则将其与right指针处的元素交换,并递减right指针。

        分区完成后,函数在左子数组和右子数组上递归调用自身以进行排序。

5.GetRandom函数

GetRandom函数在给定的左边界和右边界索引范围内生成一个随机的索引。它使用rand函数生成一个随机数,然后通过对右边界和左边界索引之间的差值加一取模,并加上左边界索引来计算索引值。

6.sortArray函数

        最后,在sortArray函数中,在开始排序过程之前,调用srand函数以用当前时间初始化随机数生成器,以确保每次运行程序时都会生成不同的随机数。

然后返回排序后的数组。


完~

未经作者同意禁止转载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/796271.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Netty 3 - 组件和设计

这里将回顾我们之前章节讲到过的主要概念和组件。 1 Channel 、EventLoop和ChannelFuture Channel —— Socket;EventLoop —— 控制流、多线程处理、并发;ChannelFuture —— 异步通知。 1.1 Channel 接口 基本的I/O操作&#xff08;bind()、connect()、read()和write()&a…

免注册,ChatGPT可即时访问了!

AI又有啥进展&#xff1f;一起看看吧 Apple进军个人家用机器人 Apple在放弃自动驾驶汽车项目并推出混合现实头显后&#xff0c;正在进军个人机器人领域&#xff0c;处于开发家用环境机器人的早期阶段 报告中提到了两种可能的机器人设计。一种是移动机器人&#xff0c;可以跟…

鸿蒙OS元服务开发:【(Stage模型)学习窗口沉浸式能力】

一、体验窗口沉浸式能力说明 在看视频、玩游戏等场景下&#xff0c;用户往往希望隐藏状态栏、导航栏等不必要的系统窗口&#xff0c;从而获得更佳的沉浸式体验。此时可以借助窗口沉浸式能力&#xff08;窗口沉浸式能力都是针对应用主窗口而言的&#xff09;&#xff0c;达到预…

二叉堆解读

在数据结构和算法中&#xff0c;二叉堆是一种非常重要的数据结构&#xff0c;它被广泛用于实现优先队列、堆排序等场景。本文将介绍二叉堆的基本概念、性质、操作以及应用场景。 一、基本概念 二叉堆是一种特殊的完全二叉树&#xff0c;它满足堆性质&#xff1a;对于每个节点…

电子商务平台中大数据的应用|主流电商平台大数据采集API接口

(一)电商平台物流管理中大数据的应用 电商平台订单详情订单列表物流信息API接口应用 电子商务企业对射频识别设备、条形码扫描设备、全球定位系统及销售网站、交通、库存等管理软件数据进行实时或近实时的分析研究,提高物流速度和准确性。部分电商平台已建立高效的物流配送网…

【STL】vector的底层原理及其实现

vector的介绍 vector是一个可变的数组序列容器。 1.vector的底层实际上就是一个数组。因此vector也可以采用连续存储空间来存储元素。也可以直接用下标访问vector的元素。我们完全可以把它就当成一个自定义类型的数组使用。 2.除了可以直接用下标访问元素&#xff0c;vector还…

掌握数据相关性新利器:基于R、Python的Copula变量相关性分析及AI大模型应用探索

在工程、水文和金融等各学科的研究中&#xff0c;总是会遇到很多变量&#xff0c;研究这些相互纠缠的变量间的相关关系是各学科的研究的重点。虽然皮尔逊相关、秩相关等相关系数提供了变量间相关关系的粗略结果&#xff0c;但这些系数都存在着无法克服的困难。例如&#xff0c;…

解决win7作为虚拟机无法复制粘贴共享文件的问题

win7作为虚拟机经常会出现无法与主机的剪切板共享、文件共享。 归根结底是win7虚拟机里面没有安装VMware Tools 能够成功安装vmware tools的条件&#xff1a; 1&#xff09;win7版本为win7 sp1及以上 2&#xff09;安装KB4490628&#xff0c;KB4474419补丁 因此下面来详细介绍…

【LeetCode题解】2192. 有向无环图中一个节点的所有祖先+1026. 节点与其祖先之间的最大差值

文章目录 [2192. 有向无环图中一个节点的所有祖先](https://leetcode.cn/problems/all-ancestors-of-a-node-in-a-directed-acyclic-graph/)思路&#xff1a;BFS记忆化搜索代码&#xff1a; 思路&#xff1a;逆向DFS代码&#xff1a; [1026. 节点与其祖先之间的最大差值](https…

为什么说AI的尽头是生物制药?

AI的尽头究竟是什么&#xff1f;有投资者说是光伏&#xff0c;也有投资者说是电力&#xff0c;而英伟达给出的答案则是生物制药。 在英伟达2023年投资版图中&#xff0c;除AI产业根基算法与基础建设外&#xff0c;生物制药是其重点布局的核心赛道。英伟达医疗保健副总裁Kimber…

FastEI论文阅读

前言 研究FastEI&#xff08;Ultra-fast and accurate electron ionization mass spectrum matching for compound identification with million-scale in-silico library&#xff09;有很长时间了&#xff0c;现在来总结一下&#xff0c;梳理一下认知。PS&#xff1a;为什么要…

【LeetCode: 21. 合并两个有序链表 + 链表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

axios快速入门

一、环境配置 1.1概述 上古浏览器页面在向服务器请求数据时&#xff0c;因为返回的是整个页面的数据&#xff0c;页面都会强制刷新一下&#xff0c;这对于用户来讲并不是很友好。并且我们只是需要修改页面的部分数据&#xff0c;但是从服务器端发送的却是整个页面的数据&#…

攻防世界 Broadcast 题目解析

Broadcast 一&#xff1a;题目 二&#xff1a;解析 将压缩包解压&#xff0c;得到如上图所示&#xff0c;打开task.py&#xff0c;之后得到flag 这个有点简单了&#xff0c;不要被解压后文件太多所迷惑。

InnoDB中的索引方案

文章目录 InnoDB中的索引方案 InnoDB支持多种类型的索引&#xff0c;包括B-tree索引、全文索引、哈希索引等。B-tree索引是InnoDB存储引擎的默认索引类型&#xff0c;适用于所有的数据类型&#xff0c;包括字符串、数字和日期等。 以下是创建InnoDB表及其B-tree索引的示例代码…

VBA数据库解决方案第九讲:把数据库的内容在工作表中显示

《VBA数据库解决方案》教程&#xff08;版权10090845&#xff09;是我推出的第二套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;是学完字典后的另一个专题讲解。数据库是数据处理的利器&#xff0c;教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…

2024年阿里云4核8G服务器多少钱一年?4C8G服务器955元

阿里云服务器4核8G租用优惠价格955元一年&#xff0c;配置为云服务器ECS通用算力型u1实例4核8G配置、ESSD Entry盘20G-40G、1M-3M带宽&#xff0c;实例规格为ecs.u1-c1m2.xlarge&#xff0c;阿里云优惠活动 yunfuwuqiba.com/go/aliyun 活动链接打开如下图&#xff1a; 阿里云4核…

【数据结构】ArrayList详解

目录 前言 1. 线性表 2. 顺序表 3. ArrayList的介绍和使用 3.1 语法格式 3.2 添加元素 3.3 删除元素 3.4 截取部分arrayList 3.5 其他方法 4. ArrayList的遍历 5.ArrayList的扩容机制 6. ArrayList的优缺点 结语 前言 在集合框架中&#xff0c;ArrayList就是一个…

spring boot学习第十六篇:配置多数据源

1、代码参考&#xff1a; dynamic-ds/spring-boot-dynamic-ds at main veminhe/dynamic-ds GitHub 2、验证 2.1调用POST接口http://localhost:8081/hmblogs/blog/addBlog 2.2改动数据源为BJ 然后调用接口添加数据 然后查看ds0库的博客数据

【最新可用】Claude国内镜像,可上传图片,可用Claude3全系模型(包括Pro版本的Opus)!亲测比GPT好用!

亲测可用&#xff0c;镜像地址&#xff1a;Claude 3 镜像 使用方法 访问镜像&#xff1a;Claude 3 镜像 2. 点击设置&#xff0c;配置授权码&#xff0c;关闭设置。这里免费赠送一个体验版的授权码 sk-SZcJyvx3RXRID624E2D3795578Df44C7Af03F2909a8f5eA0 即可发起对话啦&…