快速选择算法

news2024/9/23 21:19:40

前言

本文将会向你介绍什么是快速选择算法,(用两道例题来讲解)算法原理是什么

引入

快速选择算法和快速排序算法都是基于分治思想的算法,它们的基本原理是类似的,都是通过将数组分成两部分,然后递归地处理这两部分。

快速选择算法和快速排序算法的主要区别在于它们的应用场景和目的。

快速排序算法的目的是对整个数组进行排序,它会通过递归的方式不断地将数组分成两部分,直到整个数组有序为止。

快速选择算法的目的是在无序数组中查找第k小(或第k大)的元素,它不需要对整个数组进行排序,而是通过类似快速排序的分区操作只处理包含目标元素的那一部分数组,从而减少了不必要的操作
这种方法能够在平均情况下达到O(n)的时间复杂度,因此被广泛应用于求解第k小(或第k大)元素的问题

颜色分类

在这里插入图片描述

戳这 -> 颜色分类

类⽐数组分两块的算法思想,这⾥是将数组分成三块,那么我们可以再添加⼀个指针,实现数组分三块。
设数组⼤⼩为 n ,定义三个指针 left, i, right :

left :⽤来标记 0 序列的末尾,因此初始化为 -1 ; ◦ cur :⽤来扫描数组,初始化为 0 ;
right :⽤来标记 2 序列的起始位置,因此初始化为 n 。
在 cur 往后扫描的过程中,保证:
[0, left] 内的元素都是 0 ;
[left + 1, i - 1] 内的元素都是 1 ;
[i, right - 1] 内的元素是待定元素;
[right, n] 内的元素都是 2 。

WeChat_20231121102707

class Solution {
public:
    void sortColors(vector<int>& nums) 
    {
        int n = nums.size();
        //i:遍历区间,left:标记0区域最右侧,right:标记2区域最左侧
        // 0:[0,left]
        // 1:[left+1, i-1]
        // 待扫描区域:[i, right-1]
        // 2:[right, n-1]
        int left = -1, right = n, i = 0; 
        while(i < right)
        {
            if(nums[i] == 0)
            {
                std::swap(nums[++left], nums[i++]);
            }
            else if(nums[i] == 1)
            {
                i++;
            }
            else if(nums[i] == 2)
            {
                //i不能++,交换完后,还得判断交换后这个值是多少
                std::swap(nums[--right], nums[i]);
            }
        }
    }
};

数组中第k个最大的数

注意:要求实现时间复杂度欸O(n)的算法
在这里插入图片描述

利用颜色分类中数组分三块的思想+随机选择基准值来决定在哪一块区间中查找

WeChat_20231122093433

戳这->数组中第k个最大的数

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) 
    {
        //种下随机数种子
        srand(time(nullptr));
        return qsort(nums, 0, nums.size()-1, k);
    }

    int getRandom(vector<int>& nums, int left,int right)
    {
        //rand() % (right - left + 1)生成一个随机数范围为[0, right-left]的值,+left生成一个随机数范围为[left, right-left]
        return nums[rand() % (right - left + 1) + left];
    }

    int qsort(vector<int>& nums, int l, int r, int k)
    {
        //获得随机值
        int key = getRandom(nums, l, r);
        int left = l - 1, right = r + 1, i = l;
        //当区间只有一个元素
        if(l==r)
        {
            return nums[l];
        }
        //划分三组区间
        while(i < right)
        {
            if(nums[i] > key)
            {
                swap(nums[i], nums[--right]);
            }
            else if(nums[i] == key)
            {
                i++;
            }
            else if(nums[i] < key)
            {
                swap(nums[i++], nums[++left]);
            }
        }
        //<key      =key                >key
        //[l,left], [left+1, right-1], [right, r]
        int b = right - left - 1, c = r - right + 1;
        //(本质是缩小区间)
        //第k大的元素,在[right, r]区间中(再此区间中查找)
        if(c >= k) 
        {
            return qsort(nums, right, r, k);
        }
        //进入此条件,说明第k大的元素不在[right,r]中,在[left+1, right-1]中,而此区间的元素就是key直接返回即可
        else if(b + c >= k)
        {
            return key;
        }
        //进入此条件,第k大的元素在[l,left]中(在此区间中查找)
        else 
        {
            return qsort(nums, l, left, k - b - c);
        }
    }
};

以下是分治的思想,将数组分成三块,缩小查找范围(递归调用去找)

   <key      =key                >key
 [l,left], [left+1, right-1], [right, r]

在这里插入图片描述
此时再将新的l与r作为参数传入调用
在这里插入图片描述
当然随机数的选取的区间也变成了新的[l, r],剩余的操作就不一一演示了,大家可以自己去模拟这个过程
在这里插入图片描述

在这里插入图片描述

这里的k都只是假设出来的,当k=1时,此时c>=1, 需要到[right, r]区间中寻找最大第k个元素

在这里插入图片描述

当k=4的时候(此时运气比较好,key刚好就是第四大的数,直接返回即可) 当k=5的时候,此时b+c < k,进入[l, left]区间中寻找第(k-b-c)个数

在这里插入图片描述

其它例题

戳这->最小的k个数
戳这->排序数组

小结

今日的分享就到这里啦,后续会持续更新其他的算法讲解,如果本文存在疏忽或错误的地方还请您能够指出!

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

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

相关文章

手写promis(2)-- 链式编程篇

目录 链式编程 处理异常 和普通内容 链式编程---处理返回promise 链式编程---处理重复引用 链式编程--rejected 链式编程--处理padding状态 链式编程 处理异常 和普通内容 1.返回promise实例&#xff1a;在原本then方法里边创建新promise2.获取返回值&#xff1a;把原本…

jQuery实现横版手风琴效果

一、实现效果 当鼠标滑过方块的时候&#xff0c;方块的状态就会发生如下图所示的变化&#xff0c;同理当鼠标滑到其他的方块也会发生同样的效果&#xff0c;不仅大小会改变同时方块的颜色也会跟着发生变化&#xff1a; 二、代码实现 <!DOCTYPE html> <html><h…

如何通过提升客户体验带来更大的增长、更好的客户留存率?

客户期望的转变 在一个日益数字化的世界里&#xff0c;有必要采取以客户为中心的思维方式。因为客户与企业互动的方式有很多是在数字空间发生的&#xff0c;客户的需求和模式已经转变。 这种情况已经酝酿了几年&#xff0c;但在2020年才打开闸门。随着疫情的爆发&#xff0c;企…

java ssh 二手车交易管理系统eclipse开发mysql数据库MVC模式java编程网页设计

一、源码特点 JSP ssh 二手车交易管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用 B/S模式开发。开发环境为TOMCAT…

柯桥考级日语学校,日语听力如何拿满分

今天&#xff0c;来分析一下能力考听力中的五道听力题的题型和解题技巧。 首先在N1和N2中&#xff0c;听力题型是一样的。 第一大题「課題理解」 第二大题「ポイント理解」 第三大题「概要理解」 第四大题叫做「即時応答」 第五大题叫做「統合理解」 名字不同&#xff0c;考点和…

秋招如何准备?有什么建议?

秋招&#xff0c;是毕业生最好的求职渠道&#xff0c;没有之一。尽管还有春招&#xff0c;社招......都不如秋招重要&#xff0c;因为秋招的机会更多..... 如何准备秋招&#xff1f; 1、简历很重要 一个好的简历&#xff0c;就是敲门砖&#xff0c;这是你跟企业HR的第一次亲…

python -opencv形态学操作

python -opencv形态学操作 1.服饰和膨胀 1.服饰和膨胀 opencv 腐蚀通过cv2.erode实现&#xff0c;膨胀通过cv2.dilate实现&#xff0c;看一下下面代码&#xff1a; from ctypes.wintypes import SIZE from multiprocessing.pool import IMapUnorderedIterator import cv2 i…

20231122给RK3399的挖掘机开发板适配Android12

20231122给RK3399的挖掘机开发板适配Android12 2023/11/22 9:30 主要步骤&#xff1a; rootrootrootroot-X99-Turbo:~$ tar --use-compress-programpigz -xvpf rk356x_android12_220722.tgz rootrootrootroot-X99-Turbo:~$ cd rk_android12_220722/ rootrootrootroot-X99-Tur…

NOIP2015提高组第二轮T1:能量项链

题目链接 [NOIP2006 提高组] 能量项链 题目描述 在 Mars 星球上&#xff0c;每个 Mars 人都随身佩带着一串能量项链。在项链上有 N N N 颗能量珠。能量珠是一颗有头标记与尾标记的珠子&#xff0c;这些标记对应着某个正整数。并且&#xff0c;对于相邻的两颗珠子&#xff0…

【CodeTop】TOP 100 刷题 11-20

文章目录 11. 二叉树的层序遍历题目描述代码与解题思路 12. 搜索旋转排序数组题目描述代码与解题思路 13. 买卖股票的最佳时机题目描述代码和解题思路 14. 岛屿数量题目描述代码与解题思路 15. 环形链表题目描述代码与解题思路 16. 有效的括号题目描述代码与解题思路 17. 合并两…

呼叫中心自建好还是云外呼好用?

传统的呼叫中心在科技的发展下已经被不适用了&#xff0c;都开始使用起智能化的呼叫中心&#xff0c;一个是自建式呼叫中心&#xff0c;一个是云外呼系统。那自建式呼叫中心与云外呼系统的区别有哪些呢&#xff1f; 1、企业自建呼叫中心 劣势 系统维护更新难&#xff1a;自建…

我的创作纪念日2048天

机缘 在这特殊的日子里&#xff0c;我要庆祝我的 CSDN 创作纪念日——已经坚持了整整2048天&#xff01; 在这2048天里&#xff0c;我经历了很多成长和收获。作为一名技术写手&#xff0c;我投入了大量的时间和精力来分享我的知识和经验。我曾经写过关于数据库、数据同步、数…

AI一点通:卷积神经网络的输出节点大小如何计算?全连接层必要输入大小如何设置

在使用卷积网络&#xff08;CNN&#xff09;时&#xff0c;一个步骤是计算经过卷积和池化步骤后的输出大小&#xff0c;以便我们可以将输出连接到一个完全收集的线性层。 以Pytorch中的一维CNN为例&#xff0c; self.conv1 nn.Conv1d(in_channels1, out_channels64, kernel_s…

python数据结构与算法-10_递归

递归 Recursion is a process for solving problems by subdividing a larger problem into smaller cases of the problem itself and then solving the smaller, more trivial parts. 递归是计算机科学里出现非常多的一个概念&#xff0c;有时候用递归解决问题看起来非常简单…

面对网络渠道低价 品牌如何应对

品牌在发展过程中&#xff0c;会不断拓展自己的销售渠道&#xff0c;网站渠道是顺应消费者习惯的一种销售战场&#xff0c;没有品牌会轻易丢弃这个渠道&#xff0c;但是网络渠道的低价又是很常见的&#xff0c;所以只有及时的治理渠道低价&#xff0c;对应的渠道才会发展越来越…

【shell】shell指令学习

仅供本人自学&#xff0c;完全从自己可以理解的角度写的&#xff0c;知识点都是copy网上已有的学习资料&#xff0c;侵权请联系本人删除&#xff0c;谢谢。 1. 文本资料学习 学习Linux&#xff0c;从掌握grep、sed、awk开始吧。 Linux文本三剑客超详细教程—grep、sed、awk …

【AGC】鸿蒙应用软件包上传问题解析

【问题背景】 近期收到了一些反馈&#xff0c;一些鸿蒙元服务开发者在发布应用市场的过程中&#xff0c;上传.app包时遇到了不同的报错&#xff0c;导致上传失败&#xff0c;下面来看一下这些报错的具体原因&#xff0c;如何正确打包上传。 【问题描述1】 HarmonyOS元服务软件…

排序算法--选择排序

实现逻辑 ① 第一轮从下标为 1 到下标为 n-1 的元素中选取最小值&#xff0c;若小于第一个数&#xff0c;则交换 ② 第二轮从下标为 2 到下标为 n-1 的元素中选取最小值&#xff0c;若小于第二个数&#xff0c;则交换 ③ 依次类推下去…… void print_array(int a[], int n){f…

逐字节讲解 Redis 持久化(RDB 和 AOF)的文件格式

前言 相信各位对 Redis 的这两种持久化机制都不陌生&#xff0c;简单来说&#xff0c;RDB 就是对数据的全量备份&#xff0c;AOF 则是增量备份&#xff0c;而从 4.0 版本开始引入了混合方式&#xff0c;以 7.2.3 版本为例&#xff0c;会生成三类文件&#xff1a;RDB、AOF 和记…

这7款神仙软件,程序员必备!

如果你是程序员、开发者、网络运维等 IT 从业者日常工作中大家肯定会用到很多网站&#xff0c;今天给大家带来7款压箱底的神仙软件&#xff0c;希望可以帮助有需要的码农朋友实现更高效地办公。 一、Everything 适用&#xff1a;本地文件搜索神器 就是为了极速检索而生,其实…