【算法】分治 - 快速排序



快乐的流畅:个人主页


个人专栏:《算法神殿》《数据结构世界》《进击的C++》

远方有一堆篝火,在为久候之人燃烧!

文章目录

  • 引言
  • 一、颜色分类
  • 二、排序数组
  • 三、数组中的第k个数
  • 四、最小的k个数
  • 总结

引言

本节主要介绍快速排序(三路划分,随机取key),以及它的变形算法——快速选择算法

一、颜色分类


细节:快速排序中标准的partition(三路划分)

  • 设置三个指针 left,cur,right
  • 划分为三个区域[0, left - 1],[left, right],[right + 1, n-1]
  • [0, left - 1]:元素小于key
  • [left, right]:元素等于key
  • [right + 1, n-1]:元素大于key
  • left和right用来维护(等于key的)中路元素区域的左右两端,cur用来扫描数组
class Solution
{
public:void sortColors(vector<int>& nums){int left = 0, cur = 0, right = nums.size() - 1;while(cur <= right){if(nums[cur] == 0) swap(nums[left++], nums[cur++]);else if(nums[cur] == 2) swap(nums[right--], nums[cur]);else ++cur;}}
};

二、排序数组


思路:

  • 递归出口:区间只有一个元素或者不存在
  • 随机选key:利用rand函数,记得提前srand种下随机数种子
  • 三路划分:三指针维护区间
  • 分治:继续递归[begin, left - 1],[right + 1, end]两个区间
class Solution
{
public:int getKey(vector<int>& nums, int left, int right){int keyi = rand() % (right - left + 1) + left;return nums[keyi];}void quickSort(vector<int>& nums, int begin, int end){if(begin >= end) return;int key = getKey(nums, begin, end);//随机选keyint cur = begin, left = begin, right = end;while(cur <= right){if(nums[cur] < key) swap(nums[left++], nums[cur++]);else if(nums[cur] > key) swap(nums[right--], nums[cur]);else cur++;}quickSort(nums, begin, left - 1);quickSort(nums, right + 1, end);}vector<int> sortArray(vector<int>& nums){srand(0);//种下随机数种子quickSort(nums, 0, nums.size() - 1);return nums;}
};

三、数组中的第k个数


思路:TopK问题有三种解法

  1. 排序——O(NlogN)
  2. 堆——O(NlogK)
  3. 快速选择——O(N)

堆版本

细节:建大堆 + k-1次删除

class Solution
{
public:void AdjustDown(vector<int>& nums, int parent){int n = nums.size(), child = 2 * parent + 1;while(child < n){if(child + 1 < n && nums[child] < nums[child + 1]) ++child;if(nums[parent] < nums[child])//建大堆{swap(nums[parent], nums[child]);parent = child;child = 2 * parent + 1;}else break;}}int findKthLargest(vector<int>& nums, int k){int n = nums.size();for(int i=(n-1-1)/2; i>=0; --i){AdjustDown(nums, i);}while(--k)//执行k-1次{swap(nums[0], nums[nums.size() - 1]);nums.pop_back();AdjustDown(nums, 0);}return nums[0];}
};

快速选择版本

细节:

  • 从最右边开始数,k落在右区域,则继续递归找第k大
  • k落在中区域,则直接更新结果
  • k落在左区域,则继续递归找第k-b-c大
class Solution
{int ret;
public:int GetKey(vector<int>& nums, int begin, int end){int keyi = rand() % (end - begin + 1) + begin;return nums[keyi];}void qucikSelect(vector<int>& nums, int begin, int end, int k){if(begin > end) return;int key = GetKey(nums, begin, end);int left = begin, cur = begin, right = end;while(cur <= right){if(nums[cur] < key) swap(nums[left++], nums[cur++]);else if(nums[cur] > key) swap(nums[right--], nums[cur]);else cur++;}if(k <= end - right) qucikSelect(nums, right + 1, end, k);else if(k <= end - left + 1) ret = key;else qucikSelect(nums, begin, left - 1, k - (end - left + 1));}int findKthLargest(vector<int>& nums, int k){srand(0);qucikSelect(nums, 0, nums.size() - 1, k);return ret;}
};

四、最小的k个数



细节:

  • 从最左边开始数,k落在左区域,则继续递归找最小的k个元素
  • k落在中区域,则直接返回前k个元素
  • k落在右区域,则继续递归找最小的k-a-b个元素
class Solution
{
public:int getKey(vector<int>& nums, int begin, int end){int keyi = rand() % (end - begin + 1) + begin;return nums[keyi];}void quickSelect(vector<int>& nums, int begin, int end, int k){if(begin >= end) return;int key = getKey(nums, begin, end);int left = begin, cur = begin, right = end;while(cur <= right){if(nums[cur] < key) swap(nums[left++], nums[cur++]);else if(nums[cur] > key) swap(nums[right--], nums[cur]);else cur++;}if(k <= left - begin) quickSelect(nums, begin, left - 1, k);else if(k <= right + 1 - begin) return;else quickSelect(nums, right + 1, end, k - (right + 1 - begin));}vector<int> inventoryManagement(vector<int>& nums, int k){srand(0);quickSelect(nums, 0, nums.size() - 1, k);return {nums.begin(), nums.begin() + k};}
};

总结

快速排序,随机选key,保证了时间复杂度逼近O(NlogN),三路划分,是为了处理重复大量元素。

快速选择,是基于快速排序的变形算法,在解决TopK问题有着O(N)的时间复杂度,极其高效!


真诚点赞,手有余香

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

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

相关文章

swust oj 1012: 哈希表(链地址法处理冲突)

直接采用二维数组模拟实现 #include <iostream> using namespace std; const int N 100; int arr[N][N]; int point[N];//计数int main() {int m, n,data;cin >> m >> n;for (int i 0; i < n; i){cin >> data;int key data % m;arr[key][point[…

对于高速信号完整性,一块聊聊啊(10)

本文包含的主要内容有: 过孔设计概述:从前面的各种基础知识到过孔设计,逐步对信号完整性有了初步了解,在过孔设计这里稍微做一个概述,也是个人的一些理解,算是一个小结。 过孔设计的必要性。 过孔结构的基础知识 实例:过孔设计仿真HFSS实例 过孔设计概述 通过前面…

题目----力扣--回文链表

题目 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为 回文链表 。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;…

Kafka-生产者(producer)发送信息流程详解

Kafka概述 在 Kafka 消息发送的过程中&#xff0c;涉及到了两个重要的线程&#xff1a;主线程&#xff08;main thread&#xff09;和发送线程&#xff08;Sender thread&#xff09;。 1.主线程&#xff08;main thread&#xff09;&#xff1a; 应用程序在主线程中创建 Kaf…

详解CSS(三)及案例实现

目录 1.弹性布局 1.1 弹性布局案例 1.2flex 布局基本概念 1.3常用属性 1.3.1justify-content 1.3.2align-items 2.案例实现&#xff1a;小广告 3.案例实现&#xff1a;百度热榜 1.弹性布局 弹性布局&#xff08;Flex布局&#xff09;是一种用于创建自适应和响应式布局的…

“AIGC行业投资时机分析:评估当前市场发展阶段与未来需求趋势“

文章目录 每日一句正能量前言行业前景当前发展前景相关领域的发展趋势行业潜力竞争情况结论 市场需求人才需求情况机会挑战结论 选择与规划自我评估行业调研职业规划风险管理个人陈述示例 后记 每日一句正能量 胖了就减&#xff0c;没钱就赚&#xff0c;不会就学&#xff0c;不…

男士内裤什么材质的好?推荐男士内裤的注意事项

天气已经逐渐热了起来&#xff0c;广大男士们在夏天难免会出一身的汗&#xff0c;不少男士朋友都觉得一些吸湿性、透气性不好的内裤会在夏天穿着很不适&#xff0c;想挑选一些比较适合夏天的男士内裤&#xff0c;但现在的男士内裤品牌和材质分类却比较多&#xff0c;看得大家眼…

Python游戏编程:一步步用Python打造经典贪吃蛇小游戏

贪吃蛇作为一款极其经典且广受欢迎的小游戏&#xff0c;是早期 Windows 电脑和功能手机&#xff08;特别是诺基亚手机&#xff09;流行度极高的小游戏&#xff0c;是当时功能手机时代最具代表性的游戏之一。游戏的基本规则和目标十分简单&#xff0c;但却极具吸引力&#xff0c…

共享单车(八):数据库

实现后台数据库访问模块的框架&#xff0c;能够实现验证请求并响应&#xff08;支持数据库操作&#xff09;。 数据库设计 class SqlTabel //负责数据库表的创建 { public:SqlTabel(std::shared_ptr<MysqlConnection> sqlconn) :sqlconn_(sqlconn) {}bool CreateUserI…

详细分析crontab定时执行任务(附Demo | 定时清空Tomcat的实战)

目录 前言1. 基本知识2. Demo3. 实战3.1 错误版本3.2 正确版本 前言 由于用户量大&#xff0c;且导出的日志以及缓存特别多&#xff0c;急需定期删除文件 1. 基本知识 crontab 是一个用于定时执行任务的命令行工具&#xff0c;通常在 Unix 和类 Unix 系统中可用&#xff0c;表…

【微信小程序开发】小程序前后端交互--发送网络请求实战解析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

三、自定义信号和槽函数(无参和有参)

需求&#xff1a; 下班后&#xff0c;小明说请小红吃好吃的&#xff0c;随便吃&#xff0c;吃啥买啥 无参&#xff1a;小红没有提出吃啥 有参&#xff1a;小红提出自己想吃的东西&#xff0c;吃啥取决于一时兴起&#xff08;emit触发&#xff09; 思路&#xff1a; 1&#xff…

Unreal Engine5 Landscape地形材质无法显示加载

UE5系列文章目录 文章目录 UE5系列文章目录前言一、解决办法 前言 在使用ue5做地形编辑的时候&#xff0c;明明刚才就保存的Landscape地形完全消失不见&#xff0c;或者是地形的材质不见了。重新打开UE5发现有时候能解决&#xff0c;但大多数时候还是没有解决&#xff0c;我下…

如何在 ASP.NET Core 中实现中间件管道

概述:借助 ASP.NET Core,中间件流水线可以作为一种轻量级、灵活的机制,使开发人员能够在请求流水线的不同阶段插入功能。这些中间件组件可以执行各种任务,例如日志记录、身份验证、授权、异常处理等。它们提供了一种封装和组织代码的方法,促进了更简洁、更易于维护的应用程…

聚观早报 | 华为畅享 70S真机图赏;vivo Y200 GT开售

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 5月25日消息 华为畅享 70S真机图赏 vivo Y200 GT开售 一加13部分细节曝光 马斯克谈AI未来 三星Galaxy Z Fold6将…

有一个3x4的矩阵,要求编写程序求出其中值最大的那个元素,以及其所在的行号和列号

解题思路&#xff1a; 先考虑解此问题的思路。从若干数中求最大数的方法很多&#xff0c;现在采用"打擂台"的算法。如果有若干人比武&#xff0c;先有一人站在台上&#xff0c;再上去一人与其交手&#xff0c;败者下台&#xff0c;胜者留在台上。第3个人再上…

Font shape `U/rsfs/m/n‘ in size <29.86> not available size <24.88>

解决方法&#xff1a;mathrsfs 删除这个包 其他可以参考&#xff1a;koma script - Size substitution with fontsize14 - TeX - LaTeX Stack Exchange

【C语言】深入理解指针(一)(中)

2、指针变量和解引用操作符&#xff08;*&#xff09; &#xff08;1&#xff09;指针变量 我们通过取地址操作符&#xff08;&&#xff09;拿到的地址是一个数值&#xff0c;比如&#xff1a;0x006FFD70&#xff0c;这个数值有时候是需要存储起来&#xff0c;方便后期再…

详解最新版RabbitMQ 基于RPM 方式的安装

如何选择安装版本 已经不支持的发布系列 版本最后补丁版本首次发布时间停止更新时间3.73.7.282017年11月28日2020年09月30日3.63.6.162015年12月22日2018年05月31日3.53.5.82015年03月11日2016年10月31日3.43.4.42014年10月21日2015年10月31日3.33.3.52014年04月02日2015年03…

Mybatis Cache(一)MybatisCache+Redis

前面提到了&#xff0c;使用mybatis cache&#xff0c;一般是结合redis使用。 一、demo 1、数据表 create table demo.t_address (id int auto_incrementprimary key,address_name varchar(200) null,address_code varchar(20) null,address_type int n…