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

我爱学算法之—— 分治-快排

一、颜色分类

题目解析

在这里插入图片描述

这道题,给定一个数组nums,其中只存在012(红色、白色、蓝色);我们要将该数组分类,并按照颜色(红色、白色、蓝色)进行排序,简单来说就是将整个数组排序。

算法思路

对这道题,题目要求不使用库内置的sort,我们就可以自己实现一种排序(快排),将数组排序后返回。(红色、白色、蓝色;也就是0、1、2)。

这道题除了实现排序,我们还可以利用指针进行数组划分。思路类似我爱学算法之 —— 感受双指针带来的快感(上)中**移动0**这道题。

在移动0中,是使用双指针进行数组划分,将数组划分成两个区域(遍历过程中是三个区域)

而在这道题中,我们要将数组划分成三个区域:012。我们可以使用三指针来进行数组划分。

在这里插入图片描述

所以,在遍历数组过程中,就会将数组划分成四个区域:

在这里插入图片描述

搞懂了数组划分,那就只需搞清楚遍历过程中,遇到012,分别应该做什么操作即可。

遍历数组,遍历到i位置

  • nums[i] = 0:将该数据放入[0 , left]区域中,swap(nums[++left], nums[i++])。(left+1位置肯定是要么是1,要么就是i下标,交换left+1i下标对应的元素;然后i++0区域多了一个元素,left++
  • nums[i] = 1:将数据放到[left+1 , i]区域中,i++
  • nums[i] = 2:将数据放到[right , n-1]区域中,swap(nums[--right], nums[i])。(right-1位置属于区域[i , right-1],是未处理数据,所以交换之后不能让i++;而区域[right , n-1]中多了有数据,right--

i遍历到right位置时,数组nums中只存在三个区域(012),遍历结束。

初始化:

初始状态下,left等于-1right等于n

在这里插入图片描述

代码实现

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

二、排序数组

题目解析

在这里插入图片描述

这道题,就是一个排序数组,题目要求不使用内置函数,时间复杂度为O(n * logn),很显然就是快速排序了。

算法思路

对于快速排序,这里就不详细介绍了,可以参考博主之前文章【排序算法(二)】——冒泡排序、快速排序和归并排序—>深层解析

这里就以挖坑法来实现快速排序:

挖坑法:

  • 以最左边元素为基准值,坑位pit
  • 从右往左,找<基准值的,找到后将该值放到坑位,并更新坑位。
  • 从左往右,找>基准值的,找到后将该值放到坑位,并更新坑位。

遍历结束,将基准值填入坑位位置;这样坑位左侧的值都是<基准值的,坑位右侧的值都是>基准值的;

然后对左侧区间和右侧区间分别进行快速排序。

对于挖坑法实现的快速排序(这道题是可以通过的),这里可以对其进行优化:

优化一:

对于基准值的选择,可以使用随机选择(每次随机从[left , right]中选取一个值作为基准值)。

优化二:

对于快速排序,右边找小,左边找大,这个过程,对于等于基准值这种情况,要么是放到右侧、要么是放在左侧;这样如果数组中所有元素都相同,这种情况快速排序的时间复杂度就是O(n^2)

我们可以整个过程(Partition)进行优化,将数组划分成三个区域(小于基准值、等于基准值、大于基准值)。

这样如果数组中所有元素都相同时,只需一次递归遍历。

而对于数组划分,可上述颜色分类一样,无非就是遍历过程中判断元素和基准值的大小关系。

在这里插入图片描述

代码实现

class Solution {
public:void qsort(vector<int>& nums, int l, int r) {if (l >= r)return;// 随机选择基准值int key = nums[l + rand() % (r - l + 1)];// partitionint left = l - 1, right = r + 1;int i = l;while (i < right) {if (nums[i] < key)swap(nums[++left], nums[i++]);else if (nums[i] == key)i++;elseswap(nums[--right], nums[i]);}// 对<key区间 >key区间进行快速排序qsort(nums, l, left);qsort(nums, right, r);}vector<int> sortArray(vector<int>& nums) {srand(time(NULL));qsort(nums, 0, nums.size() - 1);return nums;}
};

三、数组中的第K个最大元素

题目解析

在这里插入图片描述

这道题要求找出数组中第k个最大的元素,典型的TOPK问题。

算法思路

思路一:

对于这道题,找出第k个最大的元素,肯定是可以使用优先级队列(堆)解决的。

建立小堆,遍历数组nums,维持堆中数据个数为k

最终堆顶元素就是第k个最大的元素。

时间复杂度:O(n * logk)

思路二:

这里题目要求我们实现时间复杂度为O(n)的算法,而使用优先级队列解决TopK问题时间复杂度为O(n * logk)

快速选择排序:

在上述排序数组题目中,我们使用数组划分来代替快速排序的partition,将数组划分成了三部分。

在这里插入图片描述

< key的区间长度为a= key的区间长度为b> key的区间长度为c

  • 如果c >=k,那第k个最大的元素肯定在> key区间中。

> key区间继续进行快速选择排序即可。(>key区间中,找第k个最大的元素

  • 如果b + c >= k,那第k个最大的元素一定就是key(区间[left+1 , right-1]=key的)
  • 如果b + c < k,那第k个最大的元素一定在< key的区间中。

< key区间继续进行快速选择排序即可。(< key区间中,找第k-b-c个最大的元素

在这里插入图片描述

代码实现

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

四、库存管理 III

题目解析

在这里插入图片描述

这道题就非常简单了,给定一个数组stock和一个整数cnt,要求我们返回一个数组,这个数组中存储的是stock中最小的cnt个数。

算法思路

这道题相对就简单很多了,这道题也算是一直TopK问题。

思路一:

解决TopK问题,创建大堆,维持堆中个数为cnt,最后将堆中元素转化成数组vector返回即可。

思路二:

将数组排序(快速排序),然后将数组前cnt个元素组成一个新的数组,然后返回。

代码实现

这里就实现将数组排序,然后将前cnt个元素组成新的数组。

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

本篇文章到这里就结束了,感谢支持
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

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

相关文章:

  • asp网站后台上传不了图片wordpress无法加载图片
  • 什么软件 做短视频网站长尾关键词有哪些
  • 江苏建设部官方网站外贸网站有必要吗
  • 企业网站规划案例长沙seo全网营销
  • 郑州营销网站公司地址天台县建设局官方网站
  • 函数调用约定
  • 迪杰斯特拉算法
  • 网站租用服务器价格个人主页网页设计模板
  • 【开题答辩实录分享】以《基于协调过滤算法的插画分享与社交网络平台的设计与实现》为例进行答辩实录分享
  • c语言定义数组
  • 网站运营问题wordpress主题报错
  • 做个网站需要多少钱?有没有旧装修要拆wordpress ck
  • 安卓基础组件024-fagment
  • Python 列表操作速查:增删改查与切片技巧
  • 泰州网站制作工具手机访问自动跳转到wap网站的代码
  • 家居企业网站建设讯息产品介绍彩页模板
  • Spring 基础核心 - SpringMVC 入门与请求流程
  • 【小沐学GIS】基于C++瓦片地图下载工具(高德/天地图/谷歌/必应/OSM/MapBox/ArcGIS)第十三期
  • 东方建设集团有限公司网站外国公司做网站
  • 微信里面如何做网站WordPress discuz 仿站
  • 【RabbitMq】七种工作模式
  • 官方网站下载cad建设部监理协会网站
  • 万方智能体投票火热进行中~
  • 不可见系统(Invisibility)
  • 建设读书网站的意义黄冈网站推广平台
  • SpringAI-Alibaba 快速开始
  • 网站制作费用一览表自己怎么设计公主房
  • 西安网站建设缑阳建中文搜索引擎排名
  • 五种IO模型,同步IO和异步IO
  • 网站开发环境安装程序nodejs wordpress