算法:分治思想处理快排递归以及快速选择/最小K个数问题

news2024/9/21 4:20:27

文章目录

  • 算法原理
  • 实现思路
  • 典型例题
    • 颜色分类
    • 快速排序优化
    • 数组中最大的K个数
    • 最小的K个数
  • 总结

算法原理

分治的原理就是分而治之,从原理上讲,就是把一个复杂的问题划分成子问题,再将子问题继续划分,直到可以解决

实现思路

基于分治的原理进行快速排序,区别于传统的快速排序,这里对快速排序进行改良,成为更优先的三路划分算法,可以处理一些极端场景,使快速排序的适用性更加广泛,同时引出快速选择算法,用来搭配堆排序解决topk问题

典型例题

颜色分类

在这里插入图片描述
本题和前面在双指针算法中做的移动0的解法类似,这里其实算法原理和快速排序优化的三路划分很相似,将数组中的区域划分为三个部分,分别为0,1,2,因此解决问题的时候要先想清楚如何解决,把数据量弄清楚

对于此题来说,算法思路就是如果遇到2,就把数据扔到最后,如果遇到0,就放到最前,那么1就会被天然的隔离到最中间的部分,这是可行的

快速排序优化

在这里插入图片描述

根据上面的原理,可以改进快速排序,快速排序的弊端在于,当他要进行处理很多相同数据的时候,就遇到十分低效的情况,基于这个原因,可以在实现它的过程中利用到一些上面的想法,这样的算法思路其实也叫做三路划分

因此可以使用这个方法来解题,否则会超时

class Solution 
{
public:
    vector<int> sortArray(vector<int>& nums) 
    {
        srand(time(0));
        quicksort(nums,0,nums.size()-1);
        return nums;
    }
    void quicksort(vector<int>& nums,int left,int right)
    {
        if(left>=right)
        {
            return;
        }
        int key=numsrandom(nums,left,right);
        int i=left,begin=left-1,end=right+1;
        while(i<end)
        {
            if(nums[i]<key)
            {
                swap(nums[++begin],nums[i++]);
            }
            else if(nums[i]==key)
            {
                i++;
            }
            else
            {
                swap(nums[--end],nums[i]);
            }
        }
        quicksort(nums,left,begin);
        quicksort(nums,end,right);
    }
    int numsrandom(vector<int>& nums,int left,int right)
    {
        int keyi=rand()%(right-left+1)+left;
        return nums[keyi];
    }
};

基于快速排序的三路划分原理,可以引申出新的思想:快速选择问题

数组中最大的K个数

在这里插入图片描述

看到这个题第一思想是使用堆排序,因为堆排序处理TopK问题是十分有效的,但是后面的限制条件,时间复杂度必须是O(N)的算法,因此这里并不能使用TopK算法

由于前面有快速排序的基础,因此这里可以引申出一个快速选择解法

首先看思路:

在快速排序的三路划分算法中,当划分结束后,整个数组会被天然的划分为下面三个部分:

在这里插入图片描述

假设,我们这里让蓝色区域的记作C,红色区域记作B,棕色区域记作A

那如果我们要求的这个第k个数据落在蓝色区域,那么我们只需要在C这个单位长度内寻找一次即可,如果落在红色区域,那么要找的这个数据就是key,如果落在棕色区域,则只需要在A这个单位长度寻找一次即可

由此,就引申出了快速选择算法:基于快速排序从而引申出的快速选择

class Solution 
{
public:
    int findKthLargest(vector<int>& nums, int k) 
    {
        srand(time(NULL));
        return quicksort(nums,0,nums.size()-1,k);
    }

    int quicksort(vector<int>& nums,int l,int r,int k)
    {
        if(l==r)
        {
            return nums[l];
        }

        // 1. 选取中间元素
        int key=getrandom(nums,l,r);
        int left=l-1,right=r+1,i=l;
        
        // 2. 三路划分
        while(i<right)
        {
            if(nums[i]<key)
            {
                swap(nums[++left],nums[i++]);
            }
            else if(nums[i]==key)
            {
                i++;
            }
            else
            {
                swap(nums[--right],nums[i]);
            }
        }

        // 3. 判断
        int c=r-right+1;
        int b=(right-1)-(left+1)+1;
        if(c>=k)
        {
            return quicksort(nums,right,r,k);
        }
        else if(b+c>=k)
        {
            return key;
        }
        else
        {
            return quicksort(nums,l,left,k-b-c);
        }
    }

    int getrandom(vector<int>& nums,int l,int r)
    {
        return nums[rand()%(r-l+1)+l];
    }
};

时间复杂度分析较为复杂,但是是严格符合题目要求的,由此其实也看出了分治的思想核心,把一个大问题转换成小问题,直到最后转换成一个我们一下就能解决的问题,不断的缩小我们需要寻找的区间,这样最终就能找到我们需要的答案

最小的K个数

在这里插入图片描述

class Solution 
{
public:
    vector<int> getLeastNumbers(vector<int>& nums, int k) 
    {
        srand(time(NULL));
        quicksort(nums,0,nums.size()-1,k);
        return {nums.begin(),nums.begin()+k};
    }

    void quicksort(vector<int>& nums,int l,int r,int k)
    {
        if(l==r)
        {
            return;
        }

        // 1. 选基准元素
        int key=getrandom(nums,l,r);
        int left=l-1,right=r+1,i=l;
        
        // 2. 三路划分
        while(i<right)
        {
            if(nums[i]<key)
            {
                swap(nums[++left],nums[i++]);
            }
            else if(nums[i]==key)
            {
                i++;
            }
            else
            {
                swap(nums[--right],nums[i]);
            }
        }

        // 3. 快速选择
        int a=left-l+1,b=(right-1)-(left+1)+1;
        if(a>k)
        {
            quicksort(nums,l,left,k);
        }
        else if(a+b>=k)
        {
            return;
        }
        else
        {
            quicksort(nums,right,r,k-a-b);
        }
    }

    int getrandom(vector<int>& nums,int l,int r)
    {
        return nums[rand()%(r-l+1)+l];
    }
};

对于这个题来说,解法多种多样,可以采用很多方法,topk,直接排序,快速选择,这里依旧选择快速选择来写

原理和前面类似,由于返回的是前k个数不一定要有序,因此三路划分后可以直接进行条件判断,满足需求就可以跳出循环

总结

分治思想用以快速排序,可以引申出快速选择这个算法,而这个算法在实际应用中有很大的作用,对于解决前k个数或第k个数都有很大的算法意义,下篇会总结分治思想用以解决归并问题

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

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

相关文章

nvm 安装nodejs

1. 下载nvm 地址&#xff1a;Releases coreybutler/nvm-windows GitHub 2. 按要求一步步进行 3. 安装完成后配置nvm 的环境变量 找到nvm文件的路径&#xff0c;选中path&#xff0c;点击编辑讲nvm的路径放进去确定保存即可

RK3562 到底性能如何?安兔兔实测

RK3562采用四核A53Mali G52架构&#xff0c;主频2GHz&#xff0c;内置1T NPU算力以及13M ISP&#xff0c;拥有丰富的外围接口。其次在解码方面&#xff0c;支持H.264 1080P60fps、H.265 4K30fps&#xff1b;编码方面支持H.264 1080P60fps&#xff0c;此外还有高质量JPEG编解码。…

无涯教程-Android Intent Standard Actions函数

下表列出了各种重要的Android Intent标准操作。您可以查看Android官方文档以获取完整的操作列表- Sr.NoActivity Action Intent & Description1 ACTION_ALL_APPS 列出设备上所有可用的应用程序。 2 ACTION_ANSWER 处理来电。 3 ACTION_ATTACH_DATA 用于表示应将某些数据…

Python股票交易---均值回归

免责声明&#xff1a;本文提供的信息仅用于教育目的&#xff0c;不应被视为专业投资建议。在做出投资决策时进行自己的研究并谨慎行事非常重要。投资涉及风险&#xff0c;您做出的任何投资决定完全由您自己负责。 在本文中&#xff0c;您将了解什么是均值回归交易算法&#xff…

你的香港公司开始年审了吗?

小青是个SOHO&#xff0c;在19年找A注册的香港公司&#xff0c;一开始是想着有个自己的公司收款或者给客户做合同的时候不需要麻烦供应商&#xff0c;会相对方便一些。公司下来之后&#xff0c;每年年审的费用也就上千块&#xff0c;还不算太高。 一开始做年审&#xff0c;都是…

Rn实现省市区三级联动

省市区三级联动选择是个很频繁的需求&#xff0c;但是查看了市面上很多插件不是太老不维护就是不满足需求&#xff0c;就试着实现一个 这个功能无任何依赖插件 功能略简单&#xff0c;但能实现需求 核心代码也尽力控制在了60行左右 pca-code.json树型数据来源 Administrative-d…

基于RabbitMQ的模拟消息队列之三——硬盘数据管理

文章目录 一、数据库管理1.设计数据库2.添加sqlite依赖3.配置application.properties文件4.创建接口MetaMapper5.创建MetaMapper.xml文件6.数据库操作7.封装数据库操作 二、文件管理1.消息持久化2.消息文件格式3.序列化/反序列化4.创建文件管理类MessageFileManager5.垃圾回收 …

【校招VIP】测试计划之测试分类

考点介绍&#xff1a; 本专题主要介绍了软件测试在不同场景下的划分。并且讲解了基于软件测试的划分衍生出的常见面试题。 测试分类也是校招里面考察的一个重点。 『测试计划之测试分类』相关题目及解析内容可点击文章末尾链接查看&#xff01; 一、考点试题 1.软件测试按开…

【安卓】拿注册码的两种方式

【安卓】拿注册码的两种方式 文章仅用于学习交流&#xff0c;请勿利用文章中的技术对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xff0c;均由使用者本人负责。首发吾爱&#xff1a;https://www.52pojie.cn/thread-1826802-1-1.html言归…

OBS Studio 30.0 承诺在 Linux 上支持英特尔 QSV,为 DeckLink 提供 HDR 回放功能

导读OBS Studio 30.0 现已推出公开测试版&#xff0c;承诺为这款广受欢迎的免费开源截屏和流媒体应用程序提供多项令人兴奋的新功能&#xff0c;以及大量其他更改和错误修复。 OBS Studio 30.0 承诺在 Linux 上支持英特尔 QSV&#xff08;快速同步视频&#xff09;、WHIP/WebRT…

Makefile介绍与使用

Make简介 工程管理器&#xff0c;顾名思义&#xff0c;是指管理较多的文件 Make工程管理器也就是个“”自动编译管理器”&#xff0c;这里的“自动”是指它能够根据文件时间戳自动发现更新过的文件而减少编译的工作量&#xff0c;同事&#xff0c;它通过读入Makefile文件的内…

问道管理:市场热点有望轮动表现 关注数据要素等主题板块

近期两市指数继续单边下行趋势仍未扭转&#xff0c;短期利好后指数虽有反弹&#xff0c;但上方仍然压力重重&#xff0c;短期或仍然以反复筑底为主。因而&#xff0c;在国内根本面仍未强势复苏前&#xff0c;指数技能面上仍然会有限制&#xff0c;短期反弹修正后或仍有反复&…

RNN循环神经网络

目录 一、卷积核与循环核 二、循环核 1.循环核引入 2.循环核&#xff1a;循环核按时间步展开。 3.循环计算层&#xff1a;向输出方向生长。 4.TF描述循环计算层 三、TF描述循环计算 四、RNN使用案例 1.数据集准备 2.Sequential中RNN 3.存储模型&#xff0c;acc和lose…

MAC M2芯片执行yolov8 + deepsort 实现目标跟踪

MAC M2芯片执行yolov8 deepsort 实现目标跟踪 MAC M2 YoloX bytetrack实现目标跟踪 实验结果 MAC mps显存太小了跑不动 还是得用服务器跑 需要实验室的服务器跑 因为网上花钱跑4天太贵了&#xff01;&#xff01;&#xff01; 步骤过程尝试&#xff1a; 执行mot17 数据集 …

FSPI的PCB设计

FSPI是一种灵活的串行接口控制器&#xff0c;RK3588芯片中有1个FSPI控制器&#xff0c;可用来连接FSPI设备。 RK3588 FSPI 控制器有如下特点&#xff1a; 1&#xff09;支持串行NOR Flash&#xff0c;串行Nand Flash&#xff1b; 2&#xff09;支持SDR模式&#xff1b; 3&am…

Android屏幕显示 android:screenOrientation configChanges 处理配置变更 代码中动态切换横竖屏

显示相关 屏幕朝向 https://developer.android.com/reference/android/content/res/Configuration.html#orientation 具体区别如下&#xff1a; activity.getResources().getConfiguration().orientation获取的是当前设备的实际屏幕方向值&#xff0c;可以动态地根据设备的旋…

【STM32】学习笔记(EXTI)-江科大

EXTI外部中断 中断&#xff1a;在主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序&#xff0c;处理完成后又返回原来被暂停的位置继续运行 中断优先级&#x…

【Python数据分析】数据分析之numpy基础

实验环境&#xff1a;建立在Python3的基础之上 numpy提供了一种数据类型&#xff0c;提供了数据分析的运算基础&#xff0c;安装方式 pip install numpy导入numpy到python项目 import numpy as np本文以案例的方式展示numpy的基本语法&#xff0c;没有介绍语法的细枝末节&am…

电商数仓项目需求及架构设计

一、项目需求 1.用户行为数据采集平台搭建 2.业务数据采集平台搭建 3.数仓维度建模 4.统计指标 5.即席查询工具&#xff0c;随时进行指标分析 6.对集群性能进行监控&#xff0c;发生异常时报警&#xff08;第三方信息&#xff09; 7.元数据管理 8.质量监控 9.权限管理&#xff…

streamlit-API

介绍 安装 pip install streamlit运行 streamlit run your_script.py [-- script args]数据流 多页应用程序 API 文本元素 数据元素 图标元素 输入小部件 媒体元素 布局和容器 聊天元素 st.chat_message st.chat_input 显示进度和状态 控制流 占位符/帮助/选项 图表改变 会…