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

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个最大的元素&#xff08;快速选择&#xff09;4、最小的k个数&#xff08;快速选择&#xff09; 分治&#xff0c;就是分而治之&#xff0c;把大问题划分成多个小问题&#xff0c;小问题再划分成更小的问题。像快排和归并排序就是分治思…...

接口用例设计

章节目录&#xff1a; 一、针对输入设计1.1 数值型1.2 字符串型1.3 数组或链表类型 二、针对业务逻辑2.1 约束条件分析2.2 操作对象分析2.3 状态转换分析2.4 时序分析 三、针对输出设计3.1 针对输出结果3.2 接口超时 四 、其他测试设计4.1 已废弃接口测试4.2 接口设计合理性分析…...

Selenium超级详细的教程

Selenium是一个用于自动化测试的工具&#xff0c;它可以模拟用户在浏览器中的各种操作。除了用于测试&#xff0c;Selenium还可以用于爬虫&#xff0c;特别是在处理动态加载页面时非常有用。本文将为您提供一个超级详细的Selenium教程&#xff0c;以帮助您快速入门并了解其各种…...

服务报network error错误

问题&#xff1a;服务请求时会偶发性的报【network error网络超时】&#xff08;请求瞬间就报&#xff09; 可能原因&#xff1a; 服务器linux内核调优时将&#xff1a;net.ipv4.tcp_tw_recycle设置为1&#xff0c;开启TCP连接中TIME-WAIT sockets的快速回收&#xff0c;默认为…...

【ES6】利用 Proxy实现函数名链式效果

利用 Proxy&#xff0c;可以将读取属性的操作&#xff08;get&#xff09;&#xff0c;转变为执行某个函数&#xff0c;从而实现属性的链式操作。 var pipe function (value) {var funcStack [];var oproxy new Proxy({} , {get : function (pipeObject, fnName) {if (fnNa…...

hive部署

下载hive安装包&#xff1a;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白名单之网段

代码托管&#xff0c;有时候为了安全性&#xff0c;限制网段内的ip可以访问。 IP地址和掩码均知道时才能确定主机所在的网段&#xff0c;也就是用这个原理来限制可访问的IP网段了。 ip后面加上“/N”就代表掩码的二进制”1“有N位。 例如&#xff1a; ①0.0.0.0/0 主机ip地…...

PMP项目管理主要学习内容是什么?

PMP项目管理是指根据美国项目管理学会(Project Management Institute&#xff0c;简称PMI)制定的项目管理知识体系和方法论进行项目管理的一种认证。PMP主要关注项目的规划、执行和控制等方面的知识和技能。 下面是PMP项目管理《PMBOK指南》第六版的主要学习内容&#xff1a; …...

小米面试题——不用加减乘除计算两数之和

前言 &#xff08;1&#xff09;刷B站看到一个面试题&#xff0c;不用加减乘除计算两数之和。 &#xff08;2&#xff09;当时我看到这个题目&#xff0c;第一反应就是感觉这是一个数电题目。不过需要采用C语言的方式编写出来。 &#xff08;3&#xff09;不过看到大佬的代码之…...

Mysql 日志管理 数据备份

MySQL日志管理 MySQL的默认日志保存位置为/usr/local/mysql/data 日志开启方式有两种&#xff1a;通过配置文件或者是通过命令 通过命令修改开启的日志是临时的&#xff0c;关闭或重启服务后就会关闭 日志的分类 1.错误日志 用来记录当MySQL启动、停止或运行时发生的错误信…...

Java小记-腾讯2020校招-后台-逛街

题目描述&#xff1a; 小Q在周末的时候和他的小伙伴来到大城市逛街&#xff0c;一条步行街上有很多高楼&#xff0c;共有n座高楼排成一行。 小Q从第一栋一直走到了最后一栋&#xff0c;小Q从来都没有见到这么多的楼&#xff0c;所以他想知道他在每栋楼的位置处能看到多少栋楼呢…...

FFmpeg5.0源码阅读——FFmpeg大体框架

摘要&#xff1a;前一段时间熟悉了下FFmpeg主流程源码实现&#xff0c;对FFmpeg的整体框架有了个大概的认识&#xff0c;因此在此做一个笔记&#xff0c;希望以比较容易理解的文字描述FFmpeg本身的结构&#xff0c;加深对FFmpeg的框架进行梳理加深理解&#xff0c;如果文章中有…...

【算法刷题之字符串篇】

目录 1.leetcode-344. 反转字符串&#xff08;1&#xff09;方法&#xff1a;双指针 2.leetcode-541. 反转字符串 II&#xff08;1&#xff09;方法一&#xff1a;模拟&#xff08;2&#xff09;方法二&#xff1a;双指针 3.leetcode-剑指 Offer 05. 替换空格&#xff08;1&…...

js中forEach和map的区别:forEach不会改变原数组,而map会改变数组?错了错了

1.提出思考&#xff1f;forEach不会改变原数组&#xff0c;而map会改变数组&#xff1f; 看到掘金上一篇文章觉得很有意思&#xff1a;大致是描述一般面试官问js中forEach和map的区别&#xff1f;都会回答forEach不会改变原数组&#xff0c;而map会改变&#xff0c;我也一直对…...

深度对话:从底层看Sui设计理念及网络规模扩展

近日&#xff0c;我们采访了George Danezis以了解Sui的交易处理系统如何促成高性能网络。他是Mysten Labs的联合创始人和首席科学家&#xff08;Sui的最初贡献者&#xff09;&#xff0c;也是伦敦大学学院&#xff08;University College London&#xff0c;UCL&#xff09;安全…...

2.单链表练习

1. 链表的基本概念 链表&#xff08;Linked List&#xff09;是一种常见的数据结构&#xff0c;用于存储一系列元素&#xff0c;这些元素可以是任意类型的数据。链表中的每个元素被称为节点&#xff08;Node&#xff09;&#xff0c;每个节点包含两部分&#xff1a;一个存储数…...

Wordpress 安装插件和主题报错

安装主题和插件的时候&#xff0c;就是这个恶心的报错&#xff0c; Wordpress plugin install: Could not create directory 这是权限惹的祸&#xff0c;如下一顿操作猛如虎&#xff0c;就解决了。 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;⭐ 如何选择⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为…...

无涯教程-机器学习 - 数据可视化

在上一章中&#xff0c;无涯教程讨论了数据对于机器学习算法的重要性&#xff0c;以了解具有统计信息的数据&#xff0c;还有另一种称为可视化的方式来理解数据。 借助数据可视化&#xff0c;可以看到数据的属性保持什么样的关联&#xff0c;这是查看要素是否与输出相对应的最…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...