【LeetCode热题100】分治-快排

news2024/12/24 19:21:18

本篇博客记录分治快排的4道题目:颜色分类、排序数组、数组中的第K个最大元素、数组中最小的N个元素(库存管理)。

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

题目分析:本题的目的旨在将nums的元素0、1、2分成三块,打算采取三指针的方法。使用left、right、i三个变量,其中,left指向全0区间的最右侧,right指向全2区间的最左侧,i指向待扫描的下一个元素,这样就把整个区间划分为4块,包括:

[0,left]:全0区域

[left+1,i-1]:全1区域

[i,right-1]:待扫描的区域

[right,n-1]:全2区域

划分好区域后,刚开始让left指向nums的左侧,即left=-1,right指向nums的右侧,即right=n,i指向nums中的第一个元素,nums[i]就会有三种情况:0、1、2。对于这三种情况,处理的动作如下图:

class Solution {
public:
    int GetRef(vector<int>& nums , int left , int right)
    {
        return nums[rand()%(right - left + 1) + left];
    }
    void _sortArray(vector<int>& nums, int left, int right)
    {
        if(left >= right) return;
        int ref = GetRef(nums, left, right);
        int l = left - 1, r = right + 1, i = left;
        while(i < r)
        {
            if(nums[i] < ref) swap(nums[++l],nums[i++]);
            else if(nums[i] == ref) i++;
            else swap(nums[--r],nums[i]);
        }
        //[left,l] [l+1,r-1] [r,right] 
        _sortArray(nums,left,l);
        _sortArray(nums,r,right);

    }
    vector<int> sortArray(vector<int>& nums) 
    {
        srand(time(NULL));
        _sortArray(nums, 0 , nums.size() - 1);
        return nums;
    }
};

题目分析:我们实现快排要用到“颜色分类”这道题的思想,向数组划分为三块,

这样迭代一次之后,[left+1,right-1]之间的元素已经排好,继续递归[0,left]和[right,n-1]即可。

在选择基准元素key时,我们可以使用随机的方式选取,ref = nums[rand()%(right-left+1)+left]。

class Solution {
public:
    int GetRef(vector<int>& nums,int left, int right)
    {
        return nums[rand()%(right-left+1)+left];
    }
    int sort(vector<int>& nums,int left, int right, int k)
    {
        if(left == right) return nums[left];
        //1.随机选择基准元素
        int ref = GetRef(nums, left, right);
        //2.根据基准元素将数组分三块
        int l = left-1,r = right+1;
        for(int i = left ; i < r ; )
        {
            if(nums[i] < ref) swap(nums[i++],nums[++l]);
            else if(nums[i] > ref) swap(nums[i],nums[--r]);
            else i++;
        }
        //3.分情况讨论
        //[left,l][l+1,r-1][r,right]
        int c = right - r + 1, b = r - l -1;
        if(c >= k) return sort(nums,r,right,k);
        else if(b+c >= k) return ref;
        else return sort(nums,left,l,k-b-c);
    }
    int findKthLargest(vector<int>& nums, int k) 
    {
        srand(time(NULL));
        return sort(nums,0,nums.size()-1,k);
    }
};

题目分析:这道题的基础依然是上面数组分三块+随机选择基准元素的思想,我们第一次将数组分成三块,[left,l][l+1,r-1][r,right],假设这三个区间的长度分别是a、b、c,然后分情况讨论:

1)c>=k,去[r,right],找第k大

2)b+c>=k,返回ref

3)如果1)和2)不成立,去[l,left],找第k-b-c大        

class Solution {
public:
    vector<int> inventoryManagement(vector<int>& nums, int cnt) 
    {
        srand(time(nullptr));
        qsort(nums,0,nums.size()-1,cnt);
        return {nums.begin(),nums.begin()+cnt};
    }
    int GetRef(vector<int>& nums,int left,int right)
    {
        return nums[rand()%(right-left+1)+left];
    }
    void qsort(vector<int>& nums,int left,int right,int cnt)
    {
        if(left == right) return;
        int ref = GetRef(nums,left,right);
        int l = left - 1,r = right + 1,i = left;
        while(i < r)
        {
            if(nums[i] < ref) swap(nums[++l],nums[i++]);
            else if(nums[i] > ref) swap(nums[--r],nums[i]);
            else i++;
        }
        //[left,l][l+1,r-1][r,right]
        int a = l - left + 1,b = r - 1 - (l + 1) + 1,c = right -r + 1;
        if(a > cnt) qsort(nums,left,l,cnt);
        else if(a + b >= cnt) return;
        else qsort(nums,r,right,cnt - a - b);
    }
};

题目分析:这道题我们有多种解法,解法1是把这些数放到一个容器中,然后进行排序,时间复杂度是OlogN。解法2是把这些数放到一个大堆里,取堆顶元素,时间复杂度是OlogK。我们这里用第三种解法,快速排序,也是利用数组分三块+随机选择基准元素的思想,在使用这个排序完一遍后,数组被分成了三块,[left,l][l+1,r-1][r,right],假设这几块的区间长度分别为a、b、c:

① a>k,继续在[left,l]中找出最小的元素。

② a+b>=k,直接返回

③ ①和②都不成立,找[right,r]中最小的k-a-b个元素,在加上[left,l]和[l+1,r-1]之间的元素。

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

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

相关文章

【实战项目】——Boost搜索引擎(五万字)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、项目的相关背景 1.1、什么是Boost库&#xff1f; 1.2、什么是搜索引擎&#xff1f; 1.3、为什么要做Boost库搜索引擎&#xff1f; 二、搜索引擎的宏观原…

VirtualBOX虚拟机提高速度,鼠标卡顿解决——未来之窗数据恢复

一、刚安装完操作系统&#xff0c;鼠标操作不灵敏 需要安装系统增强 二、系统增强作用 1.鼠标丝滑 2.文件共享 3.可以共享剪贴板 三、安装步骤-设备-安装增强 四、安装步骤-设备-选择光驱 五、安装增强软件然后重启 六、阿雪技术观 拥抱开源与共享&#xff0c;见证科技进…

【算法】动态规划:从斐波那契数列到背包问题

【算法】动态规划&#xff1a;从斐波那契数列到背包问题 文章目录 【算法】动态规划&#xff1a;从斐波那契数列到背包问题1.斐波那契数列2.爬楼梯3.零钱转换Python代码 4.零钱兑换 II5.组合数dp和排列数dp6.为什么动态规划的核心思想计算组合数的正确方法代码实现 为什么先遍历…

【C++打怪之路Lv8】-- string类

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;重生之我在学Linux&#xff0c;C打怪之路&#xff0c;python从入门到精通&#xff0c;数据结构&#xff0c;C语言&#xff0c;C语言题集&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持…

智能汽车智能网联

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c;多看一眼都是你的不…

深入理解线性表--顺序表

目录 顺序表- Seqlist -> sequence 顺序 list 表 顺序表的概念 问题与解答 顺序表的分类 静态顺序表 动态顺序表 问题与解答(递进式) 动态顺序表的实现 尾插 头插 尾删 头删 指定位置插入 指定位置删除 销毁 总结 前言&#xff1a;线性表是具有相同特性的一类数据结构…

【exceljs】纯前端如何实现Excel导出下载和上传解析?

前段时间写过一篇类似的文章&#xff0c;介绍了sheetjs。最近发现了一个更好用的库ExcelJS&#xff0c;它支持高级的样式自定义&#xff0c;并且使用起来也不复杂。实际上sheetjs也支持高级自定义样式&#xff0c;不过需要使用付费版。 下面对比了Exceljs和Sheetjs&#xff1a…

Linux的习题+一道回溯类型的算法题

Linux的习题 Linux环境与版本 1.linux 2.6.* 内核默认支持的文件系统有哪些&#xff1f;[多选] A.ext3 B.ext2 C.ext4 D.xfs E.ufs 正确答案&#xff1a;ABCD A 全称Linux extended file system, extfs,即Linux扩展文件系统&#xff0c;ext2为第二代 D XFS一种高性能的日…

使用频率最高的 opencv 基础绘图操作 - python 实现

以下是 opencv-python 基本操作绘制示例&#xff0c;绘制&#xff1a; 1&#xff09;圆&#xff0c;2&#xff09;矩形&#xff0c;3&#xff09;线段&#xff0c;4&#xff09;文本。 安装 opencv-python pip install opencv-python 在图上绘制圆的操作&#xff0c;示例如…

HCIP-HarmonyOS Application Developer 习题(五)

1、以下哪种原子化布局能力属于自适应变化能力? A. 拉伸 B.占比 C. 隐藏 D.拆行 答案&#xff1a;A 分析&#xff1a;划分为“自适应变化能力”和“自适应布局能力”两类。 其中&#xff0c;自适应变化能力包含了缩放能力和拉伸能力&#xff0c;自适应布局能力包含了隐藏、折…

『Mysql进阶』Mysql explain详解(五)

目录 Explain 介绍 Explain分析示例 explain中的列 1. id 列 2. select_type 列 3. table 列 4. partitions 列 5. type 列 6. possible_keys 列 7. key 列 8. key_len 列 9. ref 列 10. rows 列 11. filtered 列 12. Extra 列 Explain 介绍 EXPLAIN 语句提供有…

Spring学习——SpringAOP

0. IOC思想(DI)1. 关键注解Repositorypublic class DeptDaoImpl1 implements DeptDao{}RepositoryPrimarypublic class DeptDaoImpl2 implements DeptDao{}Servicepublic class DeptServiceImpl implements DeptService{AutowiredQulifier("deptDaoImpl2")private De…

UE5学习笔记24-添加武器弹药

一、给角色的武器添加弹药 1.创建界面&#xff0c;根据笔记23的界面中添加 2.绑定界面控件 UPROPERTY(meta (Bindwidget))UTextBlock* WeaponAmmoAmount;UPROPERTY(meta (Bindwidget))UTextBlock* CarriedAmmoAmount; 3.添加武器类型枚举 3.1创建武器类型枚举头文件 3.2创建文…

C++容器:map

1.铺垫 1.1map和unorder_map&#xff0c;两者的实现思想不同&#xff0c;但是用法是相同的&#xff1b;map的思想是平衡二叉树&#xff1b;unorder_map的思想是哈希&#xff1b; 1.2在现实及做题中&#xff0c;百分之99&#xff0c;都在使用unorder_map&#xff0c;接下来的讲…

2024 第一次周赛

A: 题目大意 骑士每连续 i 天每天会得到 i 个金币&#xff0c;&#xff08;i 1&#xff0c; 2&#xff0c; 3 &#xff0c; …&#xff09;,那么展开看每一天可以得到的金币数&#xff1a;1 2 2 3 3 3 4 4 4 5 5 5 5 5 … 可以发现就是1个1 &#xff0c;2个2, 3个3…,那么我…

P20机型HW睡眠省电-调研

摘要 AI睡眠场景识别 不激进的智能管控 睡眠省电 UI 以前有单独的睡眠开关选项&#xff0c;现在没有了&#xff0c;但是智能充电模式是使用AI睡眠模式 睡眠识别 华为专利上提到的论文《BTP-A Bedtime Predicting Algorithm》 各种事件状态&#xff08;亮灭屏、alarm、主动…

《数字信号处理》学习08-围线积分法(留数法)计算z 逆变换

目录 一&#xff0c;z逆变换相关概念 二&#xff0c;留数定理相关概念 三&#xff0c;习题 一&#xff0c;z逆变换相关概念 接下来开始学习z变换的反变换-z逆变换&#xff08;z反变化&#xff09;。 由象函数 求它的原序列 的过程就称为 逆变换。即 。 求z逆变换…

RTR-Chapter8

第八章 光与颜色 光量辐射度量学光度学色度学使用RGB颜色进行渲染 从场景到屏幕HDR显示编码色调映射色调再现变换曝光 颜色分级 光量 辐射度量学 辐射度量学&#xff08;radiometry&#xff09;研究的是对电磁辐射&#xff08;electromagnetic radiation&#xff09;的测量&am…

linux线程 | 线程的控制(二)

前言&#xff1a; 本节内容是线程的控制部分的第二个小节。 主要是列出我们的线程控制部分的几个细节性问题以及我们的线程分离。这些都是需要大量的代码去进行实验的。所以&#xff0c; 准备好接受新知识的友友们请耐心观看。 现在开始我们的学习吧。 ps:本节内容适合了解线程…

开源情报(OSINT)入门:初学者指南

欢迎来到令人兴奋的开源情报 (OSINT) 世界&#xff01;如果您是该领域的新手&#xff0c;OSINT 就是收集和分析公开信息以获取见解并制作情报产品。 无论您是安全爱好者、记者还是只是对 OSINT 感兴趣&#xff0c;本入门指南都将带您了解基础知识&#xff0c;让您开始第一次&a…