新闻详情

新闻详情

首页 / 资讯中心 / 详情

优选算法的妙思之流:分治——快排专题

发布时间:2026/9/27 7:31:47来源:尧图网络
优选算法的妙思之流:分治——快排专题
专栏算法的魔法世界个人主页手握风云目录一、快速排序二、例题讲解2.1. 颜色分类2.2. 排序数组2.3. 数组中的第K个最大元素2.4. 库存管理 III一、快速排序分治简单理解为“分而治之”将一个大问题划分为若干个子问题直到这个子问题能够快速解决。我们之前的快速排序是选出一个数作为基准值然后将一个数组划分为两个子序列一个序列基准值另一个基准值。但这种算法在数据特别大的时候是会超时的。所以我们这里要使用更优秀的三块划分和随机选择基准元素的算法。二、例题讲解2.1. 颜色分类这道题我们可以参照移动零里面的划分策略。移动零里面是利用双指针将数组分为0区域和非0区域这道题我们也可以使用三个指针left、right、i来将其划分为0、1、2区域。其中i用来遍历数组left用来标记0区域的最右侧right用来标记2区域的最左侧。接下来进行分类讨论如果nums[i]0我们让nums[left1]与nums[i]进行交换然后ileft就能保证[left1,i-1]区间还都是1还可能有一种极端情况就是ileft1自身与自身进行交换还是得需要left和i综上我们就可以写成nums[left]与nums[i]进行交换。如果nums[i]1我们直接就可以i就可以。如果nums[i]2时right的移动也可以参照上面left的处理--right但i不能因为i右侧是未遍历的区间如果i就会跳过这个元素。当iright时结束循环。完整代码实现class Solution { public void sortColors(int[] nums) { int left -1, right nums.length, i 0; while (i right) { if (nums[i] 0) swap(nums, left, i); else if (nums[i] 1) i; else if (nums[i] 2) swap(nums, --right, i); } } private void swap(int[] nums, int i, int j) { int tmp nums[i]; nums[i] nums[j]; nums[j] tmp; } }2.2. 排序数组这道题如果我们直接采用之前的快排思想是会超时的因为如果数组里的元素都等于基准值key这样数组元素就会跑到数组的最右侧导致时间复杂度会退化成。我们接下来利用数组分三块的思想将其划分为3个区域keykeykey。这样当基准值都等于key时时间复杂度直接降为。接下来就是如何随机选择基准值。我们需要在数组下标中等概率地选择一个下标那么我们就可以利用随机数种子利用公式r%(right-left1)left求出随机下标。完整代码实现class Solution { public int[] sortArray(int[] nums) { Quicksort(nums, 0, nums.length - 1); return nums; } private void Quicksort(int[] nums, int l, int r) { if (l r) return;//作为递归结束的条件 //数组分三块 int key nums[new Random().nextInt(r - l 1) l]; int left l - 1, right r 1, i l; while (i right) { if (nums[i] key) swap(nums, left, i); else if (nums[i] key) i; else if (nums[i] key) swap(nums, --right, i); } Quicksort(nums, l, left); Quicksort(nums, right, r); } private void swap(int[] nums, int i, int j) { int tmp nums[i]; nums[i] nums[j]; nums[j] tmp; } }2.3. 数组中的第K个最大元素因为这道题让我们用时间复杂度为所以我们的思路很明显要使用快速选择排序也就是上一题的数组分三块与随机选择基准元素。那么这个第K大的元素就有可能落在三个区域内我们设三个区域的元素个数分别为a、b、c。如果ck那我们就直接去key的这个区域去寻找如果bck就直接返回key如果前两个都不成立就去key这个区间去寻找第k-b-c大的元素。完整代码实现class Solution { public int findKthLargest(int[] nums, int k) { return Quicksort(nums, 0, nums.length - 1, k); } private int Quicksort(int[] nums, int l, int r, int k) { if (l r) return nums[l]; //随机选择基准元素 int key nums[new Random().nextInt(r - l 1) l]; //根据基准元素把数组分为三块 int left l - 1, right r 1, i l; while (i right) { if (nums[i] key) swap(nums, left, i); else if (nums[i] key) i; else if (nums[i] key) swap(nums, --right, i); } //分类讨论 //区间:[l,left],[left1,right-1],[right,r] int b right - left - 1, c r - right 1; if (c k) return Quicksort(nums, right, r, k); else if (b c k) return key; else return Quicksort(nums, l, left, k - b - c); } private void swap(int[] nums, int i, int j) { int tmp nums[i]; nums[i] nums[j]; nums[j] tmp; } }2.4. 库存管理 III题目就是求数组中的最小的cnt个数。第一种解法可以使用Arrays.sort()方法来对数组进行排序找出前k个元素第二种解法利用大根堆创建一个大小为k的大根堆将数组的前k个元素丢进大根堆中然后再将数组剩余的元素与堆顶元素比较如果小就交换并调整堆最后堆里面就是最小的k个数第三个解法就是快速选择算法。第一种解法的时间复杂度为第二种解法的时间复杂度为第三中解法的时间复杂度为。按照上一题的思路将数组分为三块三个区间内元素的个数分别为a、b、c。如果acnt那么我们只需要去key的区间去寻找如果abcnt此时的cnt一定是大于a的那么最小的cnt个数一定位于左侧两个区间而中间区间又都是等于key的所以不需要递归直接如果前两个都不成立直接去最右侧的区间去寻找第cnt-a-b个元素。完整代码实现class Solution { public int[] inventoryManagement(int[] stock, int cnt) { Quicksort(stock,0,stock.length - 1,cnt); int[] ret new int[cnt]; for (int i 0; i cnt; i) { ret[i] stock[i]; } return ret; } private void Quicksort(int[] nums, int l, int r, int k) { if(l r) return; //随机获取基准元素 int key nums[new Random().nextInt(r - l 1) l]; int left l - 1,right r 1,i l; //数组分三块 while(i right){ if(nums[i] key) swap(nums,left,i); else if (nums[i] key) i; else if (nums[i] key) swap(nums,--right,i); } //分类讨论 int a left - l 1,b right - left - 1; if(a k) Quicksort(nums,l,left,k); else if (a b k) return; else Quicksort(nums,right,r,k - a - b); } private void swap(int[] nums, int i, int j) { int tmp nums[i]; nums[i] nums[j]; nums[j] tmp; } }
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

F2 玫瑰图(南丁格尔玫瑰图)开发指南:用极坐标半径表达数据大小 2026/9/27 8:24:13

F2 玫瑰图(南丁格尔玫瑰图)开发指南:用极坐标半径表达数据大小

数据可视化前端 【免费下载链接】F2 📱📈An elegant, interactive and flexible charting library for mobile. 项目地址: https://gitcode.com/gh_mirrors/f2/F2 点击查看 免费下载 导读 玫瑰图(Rose Chart)&#x…

阅读更多 →
电脑虚拟主机避坑指南:5个关键注意事项教你省下30%预算 2026/9/27 8:24:07

电脑虚拟主机避坑指南:5个关键注意事项教你省下30%预算

电脑虚拟主机避坑指南:5个关键注意事项教你省下30%预算 找建站公司怕被坑高价?别急,先看看你选的电脑虚拟主机是否踩了这些坑。很多站长花了大价钱,网站却卡得像PPT,核心问题往往出在虚拟主机的 注意事项…

阅读更多 →
如何攻击Wordpress站点常见报错与解决 2026/9/27 8:23:46

如何攻击Wordpress站点常见报错与解决

5个WordPress安全陷阱与防御注意事项 改个需求建站公司拖一周,这种憋屈感谁懂?刚上线的WordPress站点,后台改个按钮颜色,外包团队说“底层逻辑冲突”,得排期。结果第二天网站直接变白屏,或者更糟——被黑客植入了恶意代码,SEO收…

阅读更多 →
themeforestwordpress新手避坑速查手册:别花冤枉钱 2026/9/27 8:23:46

themeforestwordpress新手避坑速查手册:别花冤枉钱

themeforestwordpress新手避坑速查手册:别花冤枉钱 网站做好了没人访问,比没做还让人焦虑。你盯着后台那可怜个位数的UV,心里直打鼓,是不是域名没选对?是不是服务器太慢?别急,这大概率不是玄学,而是技术选型和基础配置的硬伤。…

阅读更多 →
NoneBot2 跨插件访问与依赖声明:深入理解 require 机制与插件加载时序 2026/9/27 8:23:40

NoneBot2 跨插件访问与依赖声明:深入理解 require 机制与插件加载时序

后端即时通讯 【免费下载链接】nonebot2 跨平台 Python 异步聊天机器人框架 / Asynchronous multi-platform chatbot framework written in Python 项目地址: https://gitcode.com/gh_mirrors/no/nonebot2 点击查看 免费下载 跨插件调用是 NoneBot2 插件化架构中的…

阅读更多 →
基于自适应语义路由(Semantic Routing)的知识库多路混合召回实战 2026/9/27 8:23:33

基于自适应语义路由(Semantic Routing)的知识库多路混合召回实战

基于自适应语义路由(Semantic Routing)的知识库多路混合召回实战在企业级大型 RAG(检索增强生成)知识库架构中,企业通常维护着数十个物理隔离、数据形态各异的垂直专业知识库(如:API 技术文档库…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉