当前位置: 首页 > news >正文

算法篇----分治(快排)

一、解析

所谓的分治,实际上就是利用排序算法将一个数组排列成按照特定规律的顺序的样子

二、题目解析

1. 颜色分类

75. 颜色分类 - 力扣(LeetCode)

解题思路:

由于这道题只有012三个数字,我们可以找到其中间值,即遍历数组,并将其与1作比较,比1小就扔前面去,比1大就扔到后面去

为了实现上述思路,我们采用“三指针”的算法思想,即确定左右指针left和rright,之后再让变量i遍历数组,这就是三指针~

这里说明一下这三个指针所代表的意义:

left指针:其左侧(包含其本身位置)代表都是一堆0,即已经调整好的左半部分数组

i指针:遍历指针,其右侧(包含本身)为没遍历的数组

right指针:其右侧(包含其本身位置)代表都是一堆2,即已经调整好的右半部分数组

在遍历过程中会遇到如下情况:

1)nums[i] == 0 :比1小,因此要扔到前面去,可以利用swap函数, 即swap[++left,i++],这里是left在交换之前往右走一步,i在交换之后再向右走,而这里之所以可以++,是因为nums[++left]这个数也是被i扫描过的,肯定也是符合比1小的,充其量就是等于1,这种情况下大不了就自己和自己交换呗,没啥影响,但是要是比1大就要注意了~(注意区分1 3点)

2)nums[i] == 1:此时只让i++就好

3)nums[i] == 2:比1大,因此要扔到后面去,可以利用swap函数, 即swap[--right,i],这里right在交换之前向左走一步,但是切记i不要走,因为交换后i这个位置也是未经扫描修改的,换句话说nums[--right]这个数我们还没扫描过,不知道它的大致属性,还需要再次判断,重复上述过程,要是++就会跨过这个数了

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

注:这道题非常重要,下面的几道题都是基于此展开的~

2. 排序数组

912. 排序数组 - 力扣(LeetCode)

解题思路:

这道题可以利用快排思想,这里在简单复习一下快排算法:就是在一个待排数组中找一个“代表值”,之后让这个代表值找到他应该在的地方,之后整个数组被分成两个部分,之后再左右递归该操作,完成排序,此种方法排序时间复杂度为O(NlogN),但是当一整个数组都为一个数时,时间复杂度会退化为O(N^2),不是很推荐!

那么,我们可以利用三指针方法来实现快排,具体操作跟颜色那个题是一模一样的,这里就做一些补充~

1)“代表值”的寻找:可以取中间值,也可以取随机值,这里我们采用后者

2)随机值的获得:我们要种下一颗随机数种子,之后rand函数获得随机下标,进而获得随机数

3)随机下标的获取:设r=rand();则r%(right-left+1)为下标偏移量,之后在加上Left就好了

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)    //l对应左下标,r对应右下标{if(l>=r) return;      //说明数组至多一个数字//数据分三块int key=GetRandom(nums,l,r);int i=l,left=l-1,right=r+1;while(i<right){if(nums[i]<key) swap(nums[++left],nums[i++]);else if(nums[i]==key) i++;else swap(nums[--right],nums[i]);}//[l,left] [left+1,right-1] [right,r]//再对左右两部分进行快排qsort(nums,l,left);qsort(nums,right,r);}int GetRandom(vector<int>& nums,int left,int right){int r=rand()%(right-left+1)+left;return nums[r];}
};

3.数组中的第K个最大元素

215. 数组中的第K个最大元素 - 力扣(LeetCode)

解题思路:

这个就是我之前在数据结构那一专栏总结的Topk问题,这里我还是用快排解决一下吧~

注:本题是在上一道题的基础上进一步深入,请确保已经理解了前面的内容~

我们还是通过key值将数组分成如下的三段:

之后我们开始分类讨论:

1)c>=k      ->   在[right,r]里面找

2)b+c>=k   ->   返回key

3)1和2不成立  ->在[l,left],找第k-b-c大的

class Solution {
public:int findKthLargest(vector<int>& nums, int k) {return qsort(nums,0,nums.size()-1,k);}int qsort(vector<int>& nums,int l,int r,int k){if(l==r) return nums[l];//1.选择随机元素int key=GetRandom(nums,l,r);//2.分三块int left=l-1,right=r+1,i=l;while(i<right){if(nums[i]<key) swap(nums[++left],nums[i++]);else if(nums[i]==key) i++;else swap(nums[--right],nums[i]);}//3.分情况讨论int c =r-right+1,b=right-left-1;if(c>=k) return qsort(nums,right,r,k);else if(b+c>=k) return key;else return qsort(nums,l,left,k-b-c);}int GetRandom(vector<int>& nums,int left,int right){int r=rand()%(right-left+1)+left;return nums[r];}
};

4.最小k个数

LCR 159. 库存管理 III - 力扣(LeetCode)

这道题和上一道题解法几乎相同,这里就不讲解了,仅列出一张图来辅助参考

注:这里的qsort并不是要排序,只是选择而已,选出来前k个数而已,这前k个数有可能顺序还是乱的!!!

class Solution {
public:vector<int> inventoryManagement(vector<int>& stock, int cnt) {srand(time(NULL));qsort(stock,0,stock.size()-1,cnt);return {stock.begin(),stock.begin()+cnt};}void qsort(vector<int>& stock,int l,int r,int cnt){int key=GetRandom(stock,l,r);int left=l-1,right=r+1,i=l;while(i<right){if(stock[i]<key) swap(stock[++left],stock[i++]);else if(stock[i]==key) i++;else swap(stock[--right],stock[i]);}int a=left-l+1,b=right-left-1;if(a>cnt) return qsort(stock,l,left,cnt);else if(a+b>=cnt) return ;else return qsort(stock,right,r,cnt-a-b);}int GetRandom(vector<int>& stock,int l,int r){int x=rand()%(r-l+1)+l;return stock[x];}
};

分治——快排部分结束,下面将更新归并排序部分~

http://www.dtcms.com/a/322600.html

相关文章:

  • Amazon Linux 训练lora模型的方式
  • 【Canvas与旗帜】圆角蓝底大黄白星十一红白带旗
  • sqli-labs通关笔记-第39关 GET数值型堆叠注入(手工注入+脚本注入两种方法)
  • 【Linux】Tomcat
  • 2025年华数杯评审标准发布
  • 企业WEB服务器nginx新手超详细讲解
  • Docker 搭建 Jenkins 实现自动部署!
  • jenkins-飞书通知机制
  • STM32 外设驱动模块四:光敏电阻(LDR) 模块
  • Linux网络编程:TCP的远程多线程命令执行
  • Ollama 开启远程端口
  • 闲鱼智能监控机器人:基于 Playwright 与 AI 的多任务监控分析工具
  • Kubernetes 集群密钥与机密管理方案对比分析:Vault、Sealed Secrets 与 AWS KMS
  • dokcer 容器里面安装vim 编辑器
  • ruoyi关闭shiro校验,任何接口可以直接访问
  • 202506 电子学会青少年等级考试机器人五级器人理论真题
  • 【工具变量】地级市固定资产投资数据(2000-2023年)
  • 大模型在垂直场景的创新应用:搜索、推荐、营销与客服新玩法
  • LabVIEW用户事件交互
  • 【Datawhale AI夏令营】从Baseline到SOTA:深度剖析金融问答RAG管道优化之路
  • 鸿蒙示例代码使用心得
  • 华为实验: 单区域/多区域OSPF
  • n8n飞书webhook配置(飞书机器人、飞书bot、feishu bot)Crypto节点、js timestamp代码、Crypto node
  • 算法_python_学习记录_01
  • 可泛化双手操作机器人基准测试:CVPR 2025 MEIS 研讨会 RoboTwin 双臂协作挑战赛
  • day16 - CSS3新增属性
  • 【n8n教程笔记——工作流Workflow】文本课程(第二阶段)——5 自动化业务工作流——0 用例 (Use case)
  • FFMPEG将H264转HEVC时,码率缩小多少好,以及如何通过SSIM(Structural Similarity Index结构相似性指数)衡量转码损失
  • 大语言模型概述
  • day15 - CSS3新增属性