【LeetCode】排序数组——不一样的方式实现快排

目录

题目链接 

颜色分类

算法原理

代码实现

排序数组 

算法原理

代码实现

最小的k个数

算法原理

代码实现 


题目链接 

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

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

LeetCode链接:面试题 17.14. 最小K个数 - 力扣(LeetCode)

颜色分类

算法原理

我们可以将这个数组划分为三个区域,左边区域全是0也就是红色,中间区域全是1也就是白色,右边区域全是2也就是蓝色。因此我们可以用个变量i来遍历数组,变量left标记0(红色)区域的最右侧,变量right标记2(蓝色)区域的最左侧。

那么就会形成下图所示区域

  • [0, left]:全都是0
  • [left + 1, i - 1]:全都是1
  • [i, right - 1]:全都是待遍历的元素
  • [right, n - 1]:全都是2

在遍历数组的时候分情况讨论

  • 当nums[i] == 0时:我们需要将 i 位置的元素和 left + 1位置的元素进行交换,这样就能保证在left的左边都是0(包括left),,交换完后i向后移动,swap(nums[++left], nums[i++]。
  • 当nums[i] == 1时:直接i++,这样就能保证left + 1到i这个区域内都是1。
  • 当nums[i] == 2时:我们需要将 i 位置的元素和 right - 1位置的元素进行交换,这样就能保证在right的右边都是2(包括right),此时的 i 不需要移动,因为 i 到 right - 1 的这块区域都是待遍历的元素,交换后还是待遍历的元素。swap(nums[--right], nums[i])。

当i >= right时停止遍历 

代码实现

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

排序数组 

 

算法原理

 和上面颜色分类的思想是一样的,将数组划分为三块区域,左边区域为小于key的,中间区域为等于key的,右边区域为大于key的。

分类讨论:

  • 当nums[i] < key时:我们需要将 i 位置的元素和 left + 1 位置的元素进行交换,这样就能保证在left的左边全都是比key小的数(包括left),交换完后i向后移动,swap(nums[++left], nums[i++]。
  • 当nums[i] == key时:直接i++,这样就能保证left + 1到i这个区域内都是等于key的。
  • 当nums[i] > key时:我们需要将 i 位置的元素和 right - 1位置的元素进行交换,这样就能保证在right的右边都是大于key的(包括right),此时的 i 不需要移动,因为 i 到 right - 1 的这块区域都是待遍历的元素,交换后还是待遍历的元素。swap(nums[--right], nums[i])。

小优化:可以选择随机的方式来选择key值,至于为什么可以去看看算法导论这本书,里面给出了详细证明。 

代码实现

class Solution {
public:vector<int> sortArray(vector<int>& nums) {srand(time(nullptr));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);//随机取key值//分三块区域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];}
};

最小的k个数

 

算法原理

 原理和上面的排序数组一样,只是在最后要进行讨论一下k的大小

分类讨论:

  • 如果c >= k:k是落在大于key的这个区域内,只需递归这个区域找出key即可。
  • 如果b + c >= k:直接返回key就行了,因为k就落在了等于key的这个区域内。
  • 如果上面两种情况都不满足,那说明k落在了小于key这个区域内,只需找k - b - c(要把前面两个的区域去掉)大的并且递归这个区域即可。

代码实现 

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

今天的内容就分享到这里了,如果内容有错,有写的不好的地方,还望告知,谢谢!!!

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

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

相关文章

docker 部署 Epusdt - 独角数卡 dujiaoka 的 usdt 支付插件

部署 部署说明 部署之前必须注意的几点事项,该教程不一定适合所有用户: 本教程主要是使用 docker 部署,宝塔用户或宿主机直接安装的用户请直接参考官网教程.本教程是独立部署 epusdt,使用独立的mysql和redis,与dujiaoka项目分开. 在研究的过程中发现 epusdt 也需要用到 mys…

CADP加密系统的可扩展性和可定制性

CADP加密系统是一种专门用于保护CAD(计算机辅助设计)文件安全的加密解决方案。随着CAD技术在各个领域的广泛应用&#xff0c;CAD文件的安全性和保密性日益受到重视。CADP加密系统通过一系列先进的加密技术和安全措施&#xff0c;为CAD文件提供全面的保护&#xff0c;防止未经授…

ES入门十五:分页的三驾马车【from+size、search after、scroll api】

从数据集中获取数据时分页是绕不开的操作&#xff0c;一下子从数据集中获取过多的数据可能会造成系统抖动、占用带宽等问题。特别是进行全文搜索时&#xff0c;用户只关心相关性最高的那个几个结果&#xff0c;从系统中拉取过多的数据等于浪费资源。 ES提供了3种分页方式&…

Java | Leetcode Java题解之第15题三数之和

题目&#xff1a; 题解&#xff1a; class Solution {public List<List<Integer>> threeSum(int[] nums) {int n nums.length;Arrays.sort(nums);List<List<Integer>> ans new ArrayList<List<Integer>>();// 枚举 afor (int first 0;…

springboot整合ShardingSphere分库分表并插入1kw条记录

目录 一&#xff0c;数据分片 二&#xff0c;水平分片 三&#xff0c;创建数据库表 四&#xff0c;springboot项目导入依赖 五&#xff0c;创建类 六&#xff0c;bug bug放到最后了。 一&#xff0c;数据分片 数据分片指按照某个维度将存放在单一数据库中的数据分散地存…

每天学习一个Linux命令之curl

每天学习一个Linux命令之curl 在Linux系统中&#xff0c;有很多有用的命令可以帮助我们与网络进行交互。一个非常常用的命令是curl&#xff0c;它是一个功能强大的工具&#xff0c;可用于发送、接收和处理各种网络请求。本文将详细介绍在Linux下使用curl命令的各种选项及其用法…

如何理解图像处理领域的病态问题(ill-posed problem)

ill-posed problem&#xff0c;我们可以理解为病态问题或者不适定问题。在本文中&#xff0c;统一成为不适定问题。 在讨论不适定问题&#xff08;ill-posed problem&#xff09;之前&#xff0c;我们先来看一下什么叫适定性问题&#xff08;well-posed problem&#xff09;。…

如何明确的选择IT方向?

一、明确目标 作为初学者&#xff0c;先树立自己目标&#xff0c;找到自己感兴趣的IT行业&#xff0c;IT行业分很多种&#xff0c;听的最多次的无非不就是web前端工、程序员、后端、大数据、网络运维等。学习知识也是为了找到更好的工作&#xff0c;所以我建议先去boss直聘、五…

目标检测标签分配策略,难样本挖掘策略

在目标检测任务中&#xff0c;样本的划分对于模型的性能具有至关重要的影响。其中&#xff0c;正样本指的是包含目标物体的图像或区域&#xff0c;而负样本则是不包含目标物体的图像或区域。然而&#xff0c;在负样本中&#xff0c;有一部分样本由于其与正样本在特征上的相似性…

jest单元测试——项目实战

jest单元测试——项目实战 一、纯函数测试二、组件测试三、接口测试四、React Hook测试&#x1f4a5; 其他的疑难杂症另&#xff1a;好用的方法 &#x1f31f; 温故而知新&#xff1a;单元测试工具——JEST 包括&#xff1a;什么是单元测试、jest的基本配置、快照测试、mock函数…

「39」打造专业流畅的直播特效转场……

「39」工作室模式 打造专业流畅的直播特效转场体验 工作室模式是OBS软件里的一个特殊功能,用于后期直播过程中追求直播效果的用户,才会使用此功能。 该功能意在更加平滑,使用模板信息变化的过渡效果。主要用在赛事比分、活动抽奖、直播时需要经常更改的场景和内容,以及片…

Android 11属性系统初始化流程

在init进程启动的第二阶段&#xff0c;调用PropertyInit 对属性系统进行初始化 int SecondStageMain(int argc, char** argv) {//省略PropertyInit();//省略 }PropertyInit函数在system\core\init\property_service.cpp 中实现 void PropertyInit() {//省略mkdir("/dev/…

智能网联汽车自动驾驶数据记录系统DSSAD数据元素

目录 第一章 数据元素分级 第二章 数据元素分类 第三章 数据元素基本信息表 表1 车辆及自动驾驶数据记录系统基本信息 表2 车辆状态及动态信息 表3 自动驾驶系统运行信息 表4 行车环境信息 表5 驾驶员操作及状态信息 第一章 数据元素分级 自动驾驶数据记录系统记录的数…

【GameFi】 链游 | Brilliantcrypto点火活动

活动&#xff1a;https://app.galxe.com/quest/brilliantcrypto/GCt8wthq2J Brilliantcrypto点火活动正在Galxe上进行 &#x1f389; 活动时间&#xff1a;2024/04/06 12:00 ~ 2024/05/04 12:00 奖励总价值1200美元的MATIC 完成任务並在Brilliantcrypto Galxe Space上赚取积分。…

【数据结构与算法】:快速排序和冒泡排序

一&#xff0c;快速排序 快速排序是一种比较复杂的排序算法&#xff0c;它总共有4种实现方式&#xff0c;分别是挖坑法&#xff0c;左右"指针"法&#xff0c;前后"指针"法&#xff0c;以及非递归的快速排序&#xff0c;并且这些算法中也会涉及多种优化措施…

zdpdjango_materialadmin使用Django开发一个Material风格的后台管理系统

启动项目 同样地&#xff0c;还是先看看代码&#xff1a; 将项目启动起来&#xff1a; 浏览器访问&#xff1a;http://localhost:8000/ 代码初步优化 首先是将admin_materal提到本地来&#xff1a; 移除掉第三方依赖&#xff1a; pip uninstall django-admin-materi…

移动平台相关(安卓)

目录 安卓开发 Unity打包安卓 ​编辑​编辑 BuildSettings PlayerSettings OtherSettings 身份证明 配置 脚本编译 优化 PublishingSettings 调试 ReMote Android Logcat AndroidStudio的调试 Java语法 ​编辑​编辑​编辑 变量 运算符 ​编辑​编辑​编辑​…

面向低碳经济运行目标的多微网能量互联优化调度matlab程序

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 运用平台 matlabgurobi 程序简介 该程序为多微网协同优化调度模型&#xff0c;系统在保障综合效益的基础上&#xff0c;调度时优先协调微网与微网之间的能量流动&#xff0c;将与大电网的互联交互作为备用…

百度松果菁英班——机器学习实践四:文本词频分析

飞桨AI Studio星河社区-人工智能学习与实训社区 &#x1f96a;jieba分词词频统计 import jieba # jieba中文分词库 ​ with open(test.txt, r, encodingUTF-8) as novelFile:novel novelFile.read() # print(novel) stopwords [line.strip() for line in open(stop.txt, r,…

初识C++ · 类和对象(上)

目录 1.面向过程和面向对象初步认识 2.类的引入 3.类的定义 4.类的访问限定符及封装 4.1 访问限定符 4.2 封装 5.类的作用域 6.类的实例化 7.类的对象大小的计算 8.类成员函数的this指针 1.面向过程和面向对象初步认识 C语言是一门面向过程的语言&#xff0c;注重的…