C++算法 —— 分治(1)快排
文章目录
- 1、颜色分类
- 2、排序数组
- 3、第k个最大的元素(快速选择)
- 4、最小的k个数(快速选择)
分治,就是分而治之,把大问题划分成多个小问题,小问题再划分成更小的问题。像快排和归并排序就是分治思想。分治需要把数据分成几个区间,分区间则要通过基准值来划分
1、颜色分类
颜色分类

其实这道题的做法是三指针。双指针思路中,定义两个指针,假设要把整个数组划分成a和b区间,ab区间的数有各自的特点,一个指针遍历整个数组,另一个指针指向a区间的最后一个元素位置。而三指针,也是同样的思路,三个指针,abc三个区间,一个指针仍然在遍历数组,但它不需要遍历完所有,一个指针指向a区间的最右侧,一个指针指向c区间的最左侧,这样三个区间也就能划分出来了。在实际操作中,会分出四个区间

[0, left]全是0,[left + 1, i - 1]全是1,[i, right - 1]是待扫描的元素,[right, n - 1]全是2。
代码开始时,我们要如何做?left和right自然是在整个数组下标的0和n - 1处,i每次检测到数字,就去判断应该放到哪个区间,然后交换元素,把数字放到区间,left或者right移动,而i如果是放到left左边,i可以++,但是和right右边的元素交换后,i不能++,它还需要判断交换过来的数字。
void sortColors(vector<int>& nums) {int n = nums.size();int i = 0, left = -1, right = n;//为什么要这么设置left和right1的值? 看下面的代码就能明白了while(i < right)//为什么要小于right?right到最后都是为2的元素,等到i和right重合时,其实就已经完成了整体的排序{if(nums[i] == 0){swap(nums[++left], nums[i++]);}else if(nums[i] == 1){i++;}else if(nums[i] == 2){swap(nums[--right], nums[i]);}}}
2、排序数组
排序数组

其实这道题就是实现快排。我们要设置基准值key,把区间划分成两部分,<=key 和 >key,然后再到两个区间实现同样的操作,找key,划分区间。如果数组里都是重复元素的话,这个排序的复杂度就不好了。那么这里就把数组分三块的思想来实现快排,其实这个数组分三块的思路就是排序(2)那篇博客中的双指针法,思路都相似。我们要分成三个区间,< key = key > key,每次比较的时候就是交换,指针++等操作。
同上面一样
小于key:swap(nums[++left], nums[i++])
等于key:i++
大于key:swap(nus[–right], nums[i])
但是这里还有优化,上面时间复杂度是O(N),想要达成N * logN,就必须要随机选取key值。而这里的随机也不是简单的随机,我们要让整个区间的数都能等概率地没取到,我们的做法就是rand() % (right - left + 1) + left,偏移量 + left得到对应的数值,这个得出来的值是数组的下标,也就是nums[rand() % (right - left + 1) + left]。
上代码
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 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]);}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];}
3、第k个最大的元素(快速选择)
数组中的第K个最大元素

TOP K有4种问题,第k大,第k小,前k大,前k小。之前的博客对此用的是堆排序的算法。还有另外一个就是快速选择算法。堆排是O(N*logN),而快速选择是O(N)。
快速选择基于快排。整个区间左右端点为l和r,分成三个区间abc,三个区间内,我们需要确定第k大的数字在哪个区间内。假设abc就是每个区间的元素个数,如果在第三个区间,也就是>key的区间,那么c >=k;如果第一个条件不成立,那么如果在第二区间,那么b + c >=k,直接返回key就行,因为第二个区间都是=key的数字;如果上面两个条件都不成立,那么就去第一个区间找,找k - (b + c)大的数字。
int findKthLargest(vector<int>& nums, int k) {/*priority_queue<int, vector<int>, greater<int>> pq(nums.begin(), nums.begin() + k);for(size_t i = k; i < nums.size(); ++i){if(nums[i] > pq.top()){pq.pop();pq.push(nums[i]);}}return pq.top();*///上面是用优先级队列解决的srand(time(NULL));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];//必然存在至少一个元素,所以l不可能大于r//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]);}int c = r - right + 1;int 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){return [rand() % (right - left + 1) + left];}
4、最小的k个数(快速选择)
剑指 Offer 40. 最小的k个数

针对这样的问题,我们可以堆排序,也可以快速选择算法。堆排是N * logk,快速选择可以到达N。
还是l ,left, right, r,abc。如果a > k,那就在a区间找;条件不符合,那就去a + b >= k,那就返回key,因为第一个条件不符合,那么第二个条件符合的话,k一定就是在=key的区间,那就返回key;上述两种条件都不符合,那就得在c区间找。
对上一个稍作修改。
vector<int> getLeastNumbers(vector<int>& arr, int k) {srand(time(NULL));qsort(arr, 0, arr.size() - 1, k);return {arr.begin(), arr.begin() + k};}void qsort(vector<int>& nums, int l, int r, int k){if(l == r) return ;int key = getRandom(nums, l, r);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]);}int a = left - l + 1;int b = right - left - 1;if(a > k) return qsort(nums, l, left, k);else if(b + a >= k) return ;else qsort(nums, right, r, k - b - a);}int getRandom(vector<int>& nums, int left, int right){return nums[rand() % (right - left + 1) + left];}
结束。
相关文章:
C++算法 —— 分治(1)快排
文章目录 1、颜色分类2、排序数组3、第k个最大的元素(快速选择)4、最小的k个数(快速选择) 分治,就是分而治之,把大问题划分成多个小问题,小问题再划分成更小的问题。像快排和归并排序就是分治思…...
接口用例设计
章节目录: 一、针对输入设计1.1 数值型1.2 字符串型1.3 数组或链表类型 二、针对业务逻辑2.1 约束条件分析2.2 操作对象分析2.3 状态转换分析2.4 时序分析 三、针对输出设计3.1 针对输出结果3.2 接口超时 四 、其他测试设计4.1 已废弃接口测试4.2 接口设计合理性分析…...
Selenium超级详细的教程
Selenium是一个用于自动化测试的工具,它可以模拟用户在浏览器中的各种操作。除了用于测试,Selenium还可以用于爬虫,特别是在处理动态加载页面时非常有用。本文将为您提供一个超级详细的Selenium教程,以帮助您快速入门并了解其各种…...
服务报network error错误
问题:服务请求时会偶发性的报【network error网络超时】(请求瞬间就报) 可能原因: 服务器linux内核调优时将:net.ipv4.tcp_tw_recycle设置为1,开启TCP连接中TIME-WAIT sockets的快速回收,默认为…...
【ES6】利用 Proxy实现函数名链式效果
利用 Proxy,可以将读取属性的操作(get),转变为执行某个函数,从而实现属性的链式操作。 var pipe function (value) {var funcStack [];var oproxy new Proxy({} , {get : function (pipeObject, fnName) {if (fnNa…...
hive部署
下载hive安装包:https://dlcdn.apache.org/hive/hive-2.3.9/解压及环境部署 tar -zxvf apache-hive-2.3.9-bin.tar.gz mv apache-hive-2.3.9-bin hivevim /etc/profile添加至环境变量 export HIVE_HOME/usr/local/hive export PATH$PATH:$HIVE_HOME/binsource /etc…...
ip白名单之网段
代码托管,有时候为了安全性,限制网段内的ip可以访问。 IP地址和掩码均知道时才能确定主机所在的网段,也就是用这个原理来限制可访问的IP网段了。 ip后面加上“/N”就代表掩码的二进制”1“有N位。 例如: ①0.0.0.0/0 主机ip地…...
PMP项目管理主要学习内容是什么?
PMP项目管理是指根据美国项目管理学会(Project Management Institute,简称PMI)制定的项目管理知识体系和方法论进行项目管理的一种认证。PMP主要关注项目的规划、执行和控制等方面的知识和技能。 下面是PMP项目管理《PMBOK指南》第六版的主要学习内容: …...
小米面试题——不用加减乘除计算两数之和
前言 (1)刷B站看到一个面试题,不用加减乘除计算两数之和。 (2)当时我看到这个题目,第一反应就是感觉这是一个数电题目。不过需要采用C语言的方式编写出来。 (3)不过看到大佬的代码之…...
Mysql 日志管理 数据备份
MySQL日志管理 MySQL的默认日志保存位置为/usr/local/mysql/data 日志开启方式有两种:通过配置文件或者是通过命令 通过命令修改开启的日志是临时的,关闭或重启服务后就会关闭 日志的分类 1.错误日志 用来记录当MySQL启动、停止或运行时发生的错误信…...
Java小记-腾讯2020校招-后台-逛街
题目描述: 小Q在周末的时候和他的小伙伴来到大城市逛街,一条步行街上有很多高楼,共有n座高楼排成一行。 小Q从第一栋一直走到了最后一栋,小Q从来都没有见到这么多的楼,所以他想知道他在每栋楼的位置处能看到多少栋楼呢…...
FFmpeg5.0源码阅读——FFmpeg大体框架
摘要:前一段时间熟悉了下FFmpeg主流程源码实现,对FFmpeg的整体框架有了个大概的认识,因此在此做一个笔记,希望以比较容易理解的文字描述FFmpeg本身的结构,加深对FFmpeg的框架进行梳理加深理解,如果文章中有…...
【算法刷题之字符串篇】
目录 1.leetcode-344. 反转字符串(1)方法:双指针 2.leetcode-541. 反转字符串 II(1)方法一:模拟(2)方法二:双指针 3.leetcode-剑指 Offer 05. 替换空格(1&…...
js中forEach和map的区别:forEach不会改变原数组,而map会改变数组?错了错了
1.提出思考?forEach不会改变原数组,而map会改变数组? 看到掘金上一篇文章觉得很有意思:大致是描述一般面试官问js中forEach和map的区别?都会回答forEach不会改变原数组,而map会改变,我也一直对…...
深度对话:从底层看Sui设计理念及网络规模扩展
近日,我们采访了George Danezis以了解Sui的交易处理系统如何促成高性能网络。他是Mysten Labs的联合创始人和首席科学家(Sui的最初贡献者),也是伦敦大学学院(University College London,UCL)安全…...
2.单链表练习
1. 链表的基本概念 链表(Linked List)是一种常见的数据结构,用于存储一系列元素,这些元素可以是任意类型的数据。链表中的每个元素被称为节点(Node),每个节点包含两部分:一个存储数…...
Wordpress 安装插件和主题报错
安装主题和插件的时候,就是这个恶心的报错, Wordpress plugin install: Could not create directory 这是权限惹的祸,如下一顿操作猛如虎,就解决了。 sudo chown -R www:www wp-content/themes sudo chown -R www:www wp-conte…...
Spring Cloud 2022.x版本使用gateway和nacos实现动态路由和负载均衡
文章目录 1、nacos下载安装1.1、启动服务器1.2、关闭服务器1.3、服务注册&发现和配置管理接口 2、代码示例2.1、app1工程代码2.2、app2工程代码2.3、gateway网关工程代码 3、动态配置网关路由3.1、配置动态路由3.2、配置为负载模式 4、gateway配置规则4.1、请求转发&#x…...
CSS中如何隐藏元素但保留其占位空间(display:none vs visibility:hidden)?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ display: none;⭐ visibility: hidden;⭐ 如何选择⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为…...
无涯教程-机器学习 - 数据可视化
在上一章中,无涯教程讨论了数据对于机器学习算法的重要性,以了解具有统计信息的数据,还有另一种称为可视化的方式来理解数据。 借助数据可视化,可以看到数据的属性保持什么样的关联,这是查看要素是否与输出相对应的最…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
高效的后台管理系统——可进行二次开发
随着互联网技术的迅猛发展,企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心,成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统,它不仅支持跨平台应用,还能提供丰富…...
