【Python】优雅的快速选择 - 快速排序 - 随机快速排序

快速选择(递归实现版)

这里给出以 “leetcode215. 数组中的第K个最大元素”为例的代码。

class Solution:def findKthLargest(self, nums, k):self.nums = numsn = len(nums)return self.quickSelect(0,n-1,n-k)def quickSelect(self,l,r,k): # 手撸快速选择if(l == r): return self.nums[k]mid_num = self.nums[l]i = l-1j = r+1while(i < j):i += 1while(self.nums[i] < mid_num): i += 1j -= 1while(self.nums[j] > mid_num): j -= 1if(i < j): self.nums[i],self.nums[j] = self.nums[j],self.nums[i]if(k <= j): return self.quickSelect(l,j,k)return self.quickSelect(j+1,r,k)

代码的实现参照了官解,非常优雅。

代码的关键是,"while(i < j):"这一步里面的循环。可以证明,经过这个循环,最后出来的j,其位置一定在区间[l,r-1]上,同时[l,j]元素的值均等小于等于[j+1,r]。因此,每次递归,都会导致输入的数组长度减少,递归可以退出。由于寻找的是下标为k的排序的元素,因此每次分割,一定可以确定有一边是不必再排序的,因此进入下一递归的区间,就选择[l,j]或[j+1,r],直到某个递归中l=r,这时代表只有一个元素,没必要排序,直接返回此时列表的下标k的元素即可得到。

注意代码实现中的,选择第一个元素作为基准值的设计很精妙,可以仔细品鉴。

快速选择(迭代实现)

class Solution:def findKthLargest(self, nums, k):self.nums = numsn = len(nums)return self.quickSelectIter(0,n-1,n-k) def quickSelectIter(self,l,r,k): # 手撸快速选择while(l != r):mid_num = self.nums[l]i = l-1j = r+1while(i < j):i += 1while(self.nums[i] < mid_num): i += 1j -= 1while(self.nums[j] > mid_num): j -= 1if(i < j): self.nums[i],self.nums[j] = self.nums[j],self.nums[i]if(k <= j):l,r = l,jelse:l,r = j+1,rreturn self.nums[k]

快速排序

上面的快速选择,每次划分成两个区间,然后抛弃另一个区间,继续划分留下的区间。
对上面的代码稍加改进,对每个划分出的区间继续划分,即可得到完全排序的数组。

这里以"leetcode 912. 排序数组"给出代码

class Solution:def sortArray(self, nums: List[int]) -> List[int]:self.nums = numsself.quickSort(0,len(nums)-1)return numsdef quickSort(self,l,r):if(l == r): returnmid_num = self.nums[l]i = l-1j = r+1while(i < j):i += 1while(self.nums[i] < mid_num): i += 1j -= 1while(self.nums[j] > mid_num): j -= 1if(i < j): self.nums[i],self.nums[j] = self.nums[j],self.nums[i]self.quickSort(l,j)self.quickSort(j+1,r)

随机快速排序

上面的快速排序,取第一个元素为基准值,会导致在极端情况下,时间开销大。比如数组已经是有序的情况。

这里做出改进,随机选取数组中的一个元素作为基准值。但是,前面快速选择的方法中实现的划分是精心设计的,其要求基准值是第一个元素。
因此,在随机选择基准值并划分的实现上,只需先随机选取一个下标,并将下标值和第一个值互换,其它操作和之前一样即可。

class Solution:def sortArray(self, nums: List[int]) -> List[int]:self.nums = numsself.quickSortRandom(0,len(nums)-1)return nums# 随机快速排序def quickSortRandom(self,l,r):if(l == r): returnrandom_index = random.randint(l, r)self.nums[l],self.nums[random_index] = self.nums[random_index],self.nums[l]mid_num = self.nums[l]i = l-1j = r+1while(i < j):i += 1while(self.nums[i] < mid_num): i += 1j -= 1while(self.nums[j] > mid_num): j -= 1if(i < j): self.nums[i],self.nums[j] = self.nums[j],self.nums[i]self.quickSortRandom(l,j)self.quickSortRandom(j+1,r)

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

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

相关文章

Vue3实战笔记(64)—Vue 3自定义指令的艺术:实战中的最佳实践

文章目录 前言一、一些简单的Vue3自定义指令超实用案例总结 前言 书接上文&#xff0c;在Vue3中&#xff0c;自定义指令是一种强大的工具&#xff0c;允许我们扩展HTML元素的功能。通过自定义指令&#xff0c;我们可以创建可重用的行为&#xff0c;并将它们绑定到任何元素上。…

订单折扣金额分摊算法|代金券分摊|收银系统|积分分摊|分摊|精度问题|按比例分配|钱分摊|钱分配

一个金额分摊的算法&#xff0c;将折扣分摊按比例&#xff08;细单实收在总体的占比&#xff09;到各个细单中。 此算法需要达到以下要求&#xff1a; 折扣金额接近细单总额&#xff0c;甚至折扣金额等于细单金额&#xff0c;某些时候甚至超过细单总额&#xff0c;要保证实收不…

游泳哪个牌子好?6大游泳耳机选购技巧总结分享

游泳耳机作为水上运动爱好者和游泳专业人士的必备装备&#xff0c;不仅要能够抵御水的侵入&#xff0c;还要提供清晰的音质和舒适的佩戴体验。在市面上&#xff0c;不同品牌的游泳耳机琳琅满目&#xff0c;选择起来可能会令人头疼。本文旨在为您提供一份详尽的游泳耳机选购指南…

每日一练 - Routing Policy节点逻辑

01 真题题目 一个 routing-policy 下可以有多个节点,不同节点号用 node 标识,每个节点下可以有多个if-match 和 apply 子句,下面哪些描述是错误的? A. 不同节点之间是“或"的关系 B. 当路由与该节点的任意一个 if-match 条件匹配失败后&#xff0c;系统自动转入下一节点…

Gemma轻量级开放模型在个人PC上释放强大性能,让每个桌面秒变AI工作站

Google DeepMind团队最近推出了Gemma&#xff0c;这是一个基于其先前Gemini模型研究和技术的开放模型家族。这些模型专为语言理解、推理和安全性而设计&#xff0c;具有轻量级和高性能的特点。 Gemma 7B模型在不同能力领域的语言理解和生成性能&#xff0c;与同样规模的开放模型…

名企专访|对抗价格内卷,格行随身WiFi如何持续三年爆火引领潮流

近期要是问网红达人最喜欢带货的单品是什么&#xff1f;那一定有格行随身WiFi的一席之地。能聚集了如此多的明星达人&#xff0c;仅仅是一句带货收益高显然无法说服大家。显然这里面还有着不为人知的秘密&#xff0c;先锋财经特意专访了格行随身WiFi的创始人刘永先先生&#xf…

8.x86游戏实战-OD详解

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 上一个内容&#xff1a;7.x86游戏实战-C实现跨进程读写-跨进程写内存 工具下载&#xff1a;下载 OllyI…

嵌入式Linux之Uboot简介和移植

uboot简介 uboot 的全称是 Universal Boot Loader&#xff0c;uboot 是一个遵循 GPL 协议的开源软件&#xff0c;uboot是一个裸机代码&#xff0c;可以看作是一个裸机综合例程。现在的 uboot 已经支持液晶屏、网络、USB 等高级功能。 也就是说&#xff0c;可以在没有系统的情况…

[我靠升级逆袭成为大师]韩漫日漫无删减完整版,免费在线观看漫画

[我靠升级逆袭成为大师]韩漫日漫无删减完整版&#xff0c;免费在线观看漫画 不能多说&#xff0c;怕审-核不过&#xff0c;自己看图吧。 目前统计【统计日期&#xff1a;2024-07-03】&#xff1a; 完结的有&#xff1a;420部。 连载的有&#xff1a;308部&#xff0c;持续更…

生单链路流程复杂,涉及到上下游商品、库存、营销、风控、拆单、校验、落库等等十多个节点操作,需要保证数据的完整性和正确性

处理复杂的生单链路流程&#xff0c;确保数据的完整性和正确性&#xff0c;需要一个综合的策略&#xff0c;包括但不限于以下几个方面&#xff1a; 1. **流程设计**&#xff1a; - 明确每个节点的职责和输入输出&#xff0c;确保流程的逻辑清晰。 2. **数据校验**&#xf…

python库(1):Nuitka库

1 Nuitka介绍 Nuitka是一个 Python 解释器的替代品&#xff0c;支持CPython提供的代码&#xff0c;可编译 Python 代码到 C 程序&#xff0c;并使用 libpython 来执行这些代码&#xff0c;就像 CPython 一样。 这让你可以在没有安装 Python 的环境中运行 Python 程序&#xf…

AC7801时钟配置流程

一 默认配置 在启动文件中&#xff0c;已经对时钟进行了初始化&#xff0c;默认按外部8M晶振&#xff0c;配置系统时钟为48MHZ&#xff0c;APB为系统时钟的2分频&#xff0c;为24MHZ。在system_ac780x.c文件中&#xff0c;可以找到下面这个系统初始化函数&#xff0c;里面有Se…

前端修改audio背景色

1.查看浏览器设置Show user agent shadow DOM是否打开 2.打开可以查看audio Dom /** 去掉默认的背景颜色 */ audio::-webkit-media-controls-enclosure{background-color:unset; } 3.效果图

Java官网网址及其重要资源

Java是一种广泛应用于开发各种应用程序的编程语言&#xff0c;它具有跨平台、面向对象和高性能等优势。若你想学习Java或深入了解它的最新动态&#xff0c;Java官网是你的首要目的地。在本文中&#xff0c;我们将向你介绍Java官网的网址以及一些重要资源。 Java官网网址&#x…

TCP/IP 网络协议族分层

TCP/IP协议族 TCP/IP不单是TCP和IP两个协议&#xff0c;TCP/IP实际上是一组协议&#xff0c;它包括上百个各种功能的协议&#xff0c;如&#xff1a;远程登录、文件传输和电子邮件等&#xff0c;当然&#xff0c;也包括TCP、IP协议 它将软件通信过程抽象化为四个抽象层&#…

基于SpringBoot校园外卖配送系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

c++:关键字异常处理机制

模板编程的几个关键字 模(mu)板编程初体验 (1)template和typename (2)模板实际上是一种抽象&#xff0c;C的高级编程特性就是不断向抽象化发展 export (1)用来在cpp文件中定义一个模板类或模板函数&#xff0c;而它的声明在对应的h文件中 (2)export专用于模板&#xff0c;类似…

揭秘电子世界的双雄:模拟电路与数字电路的精彩对决!

数字电路与模拟电路&#xff0c;这两者在电子工程领域可谓是两大基石&#xff0c;各有千秋&#xff0c;各自发挥着不可或缺的作用。下面&#xff0c;我们就来详细探讨一下它们之间的主要区别。 1. 信号类型与处理 模拟电路&#xff1a;处理的是连续变化的信号&#xff0c;就像…

使用阿里云语音服务实现设备异常实时通知

随着物联网的普及,设备异常通知方式也变得多种多样。从传统的后台异常列表,到短信通知,再到微信消息通知等。然而,当设备探测到火警等紧急异常时,需要实时通知到相关人员。本文将介绍如何借助阿里云的语音服务来实现这一功能。 1. 准备工作 1.1 资质申请 首先,登录阿里…

Git中fetch与pull 的区别

一、fetch与pull的基本概念 在Git中&#xff0c;fetch和pull都是用于从远程仓库获取数据的命令。但是&#xff0c;它们在处理方式和结果上有所不同。 1、fetch fetch命令用于从远程仓库下载最新的数据到本地仓库&#xff0c;但它不会自动合并或修改当前的工作。fetch会将远程…