【算法】【数组与矩阵模块】求无序数组中前k个小的数

news/2024/4/25 23:38:09/文章来源:https://blog.csdn.net/qq_39760347/article/details/129132282

目录

  • 前言
  • 问题介绍
  • 解决方案
  • 代码编写
    • java语言版本
    • c语言版本
    • c++语言版本
  • 思考感悟
  • 写在最后

前言

当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~

在此感谢左大神让我对算法有了新的感悟认识!

问题介绍

原问题
给定一个数组arr和一个正整数k,求arr的前k个小的数

解决方案

原问题
堆解法:
维护一个长度为k的大根堆(如果求前k个小的值),堆如果没满则进入堆底并上浮,如果堆满了,则判断堆顶(当前最大值),比堆顶大则不需要入堆,比堆顶小,则将堆顶替换掉,进行一次下沉操作即可
时间复杂度:O(nlogn)
BFPRT算法:
该算法能够找到全局第k小的数,剩下只需要再遍历一次数组即可,该算法有以下几个步骤:
定义一个方法能够从当前数组arr中获取第k个小的值
1、将arr中n个元素划分成n/5组,每一组有5个元素,左右剩余不足5个元素的自成一组
2、将每组元素进行插入排序,并求出中位数,一共存在n/5+1或者n/5个中位数
3、将中位数组拿到后再次找到中位数的中位数,这次不再使用插排法或者而是递归使用定义的方法,换一种说法就是找到第len/2小的值也就是中位数
4、根据找到的中位数的中位数x,将数组进行一次快排划分,将小于x的放到左边,大于x的放到右边,等于的放到中间
5、判断x的位置范围(因为有可能存在与x相等的元素),如果k值再x范围中间,则直接返回x,x就是第k小的数,如果在左边,则左边继续进行递归找第k小的数,如果在右边,则右边继续递归找第 k-(x最右边的那个index)小的数.
6、找到之后再次遍历数组即可
时间复杂度:O(n)

代码编写

java语言版本

原问题:

    /*** 二轮测试:求arr中前k个小的数** @param arr* @return*/public static int[] printKMinCp1(int[] arr, int k) {if (arr == null || arr.length == 0 || k <= 0) {return null;}// 维护一个k大小的大根堆int[] res = new int[k];for (int i = 0; i < arr.length; i++) {if (i < k) {// 说明堆没有满heapInsertCp1(res, i, arr[i]);} else {// 说明堆满了,比较头节点if (arr[i] < res[0]) {// 替换顶res[0] = arr[i];// 进行一波下沉,因为这里堆已经满了,所以就不写通用的推下沉方法了,正常来说应该要给一个sizeheapify(res, 0);}}}return res;}/*** 从i处开始下城** @param res* @param i*/private static void heapify(int[] res, int i) {int size = res.length;// 申请内存int parent = i;int left = parent * 2 + 1;while (left < size) {// 先跟左节点比较出大值int maxIndex = res[parent] < res[left] ? left : parent;// 判断右节点是否存在,是否右节点更大int right = left + 1;if (right < size && res[right] > res[maxIndex]) {// parent需要和right交换maxIndex = right;}// 判断是否交换if (maxIndex == parent) {// 不用交换直接退出break;}// 需要交换CommonUtils.swap(res, parent, maxIndex);// 更新parent和leftparent = maxIndex;left = parent * 2 + 1;}}/*** 将value插入到arr的index处并进行一波上浮操作** @param res* @param index* @param value*/private static void heapInsertCp1(int[] res, int index, int value) {res[index] = value;int i = index;while (i != 0) {// 计算出父节点int parent = (i - 1) / 2;if (res[parent] < value) {// 交换CommonUtils.swap(res, parent, i);// 继续下一轮i = parent;} else {break;}}}public static void main(String[] args) {CommonUtils.printArr(printKMinCp2(new int[]{5, 3, 6, 1, 2, 7, 4}, 3));}

BFPRT算法:

/*** 二轮测试:方法2,BFPRT 算法求arr中前k个小的数** @param arr* @return*/public static int[] printKMinCp2(int[] arr, int k) {if (arr == null || arr.length == 0 || k <= 0) {return null;}// arr中第k小的数的位置int kMin = BFPRTCP2(arr, k);int[] res = new int[k];int index = 0;for (int i = 0; i < arr.length; i++) {if (index == k) {break;} else {if (arr[i] < kMin) {res[index++] = arr[i];}}}// 将剩下的多余位置都变成kminwhile (index < k) {res[index++] = kMin;}return res;}private static int BFPRTCP2(int[] arr, int k) {return selectCp1(arr, 0, arr.length - 1, k - 1);// 分数组// 各数组插入排序,选出中位数并组成一个新的arr// 求新的arr中第arr.lenth/2 小的数,即为midIndex// 重新调整数组,算出中间值mid的新位置// k==mid,返回,小于 求左边,大于求右边}/*** 递归主体** @param arr* @param start* @param end* @param k* @return*/private static int selectCp1(int[] arr, int start, int end, int k) {if (start == end) {return arr[start];}int mid = getMidOfMid(arr, start, end);int[] range = getRange(arr, start, end, mid);if (k >= range[0] && k <= range[1]) {return arr[k];} else if (k <= range[0]) {// 在左边return selectCp1(arr, 0, range[0] - 1, k);} else {// 在右边return selectCp1(arr, range[1] + 1, end, k - range[1]);}}private static int[] getRange(int[] arr, int start, int end, int mid) {// 两个边界int small = start - 1;int big = end + 1;int cur = start;while (cur < big) {if (arr[cur] < mid) {CommonUtils.swap(arr, ++small, cur++);} else if (arr[cur] > mid) {CommonUtils.swap(arr, cur, --big);} else {cur++;}}return new int[]{small + 1, big - 1};}/*** 获取中位数的中位数** @param arr* @param start* @param end* @return*/private static int getMidOfMid(int[] arr, int start, int end) {// 中位数个数计算int len = (end - start + 1) / 5 + ((end-start+1) % 5 == 0 ? 0 : 1);// 中位数容器int[] midArr = new int[len];for (int i = 0; i < midArr.length; i++) {// 循环计算中位数midArr[i] = getMid(arr, i * 5, i * 5 + 5 > end ? end : i * 5 + 4);}// 计算中位数的中位数return selectCp1(midArr, 0, midArr.length-1, midArr.length / 2);}/*** 获取midarr的中位数** @param midArr* @param start* @param end* @return*/private static int getMid(int[] midArr, int start, int end) {// 插入排序insertSortCp2(midArr, start, end);// 找到中位数,偶数为下中位数return midArr[(start + end) / 2 + ((end - start+1) % 2 == 0 ? 1 : 0)];}/*** 插入排序** @param midArr* @param start* @param end*/private static void insertSortCp2(int[] midArr, int start, int end) {for (int i = start; i <= end; i++) {for (int j = i; j > start; j--) {if (midArr[j] < midArr[j - 1]) {CommonUtils.swap(midArr, j, j - 1);} else {break;}}}}

c语言版本

正在学习中

c++语言版本

正在学习中

思考感悟

这道题我最先想到的也是堆排序,其实如果是面试,写出堆排序基本就没什么问题了,然后出现了一个课外的BFPRT算法,证明大家可以去找一下,看起来时间复杂度好像还挺高,但是最后证明确实是O(N)有兴趣的同学可以看下算法导论。

写在最后

方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!

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

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

相关文章

虹科新闻 | 虹科与b-plus正式建立合作伙伴关系,共同致力于用于ADAS/AD系统开发的VV测量解决方案

虹科b-plus 携手共创未来&#xff01; 近期&#xff0c;虹科与德国b-plus正式建立合作伙伴关系。未来&#xff0c;虹科与b-plus将共同致力于提供用于ADAS/AD系统开发的V&V测量解决方案。 合作寄语 虹科CEO陈秋苑女士表示&#xff1a;“虹科非常期待与b-plus合作&#x…

Microsoft Dynamics 365:导入License到服务层,通过Business Central Administration Shell

本文主要是Microsoft Dynamics 365的License导入的图解干货&#xff0c;不多赘述&#xff0c;直接上图&#xff1a;第一步&#xff1a;准备好的License文件放在你喜欢的目录下第二步&#xff1a;到开始程序里找到并打开 Business Central Administration Shell3.第三步&#xf…

Day895.MySql误删数据还原方案 -MySQL实战

MySql误删数据还原方案 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于MySql误删数据还原方案的内容。 传统的高可用架构是不能预防误删数据的&#xff0c;因为主库的一个 drop table 命令&#xff0c;会通过 binlog 传给所有从库和级联从库&#xff0c;进而导致整…

ASE20N60-ASEMI的MOS管ASE20N60

编辑-Z ASE20N60在TO-247封装里的静态漏极源导通电阻&#xff08;RDS(ON)&#xff09;为0.4Ω&#xff0c;是一款N沟道高压MOS管。ASE20N60的最大脉冲正向电流ISM为80A&#xff0c;零栅极电压漏极电流(IDSS)为10uA&#xff0c;其工作时耐温度范围为-55~150摄氏度。ASE20N60功耗…

UVM实战--加法器

前言 这里以UVM实战&#xff08;张强&#xff09;第二章为基础修改原有的DUT&#xff0c;将DUT修改为加法器&#xff0c;从而修改代码以使得更加深入的了解各个组件的类型和使用。 一. 组件的基本框架 和第二章的平台的主要区别点 &#xff08;1&#xff09;有两个transactio…

我的三周年创作纪念日——学习不止,创作不停

机缘 最开始写文章博客&#xff0c;是为了用输出倒逼自己输入。 从校园离开后&#xff0c;才逐渐意识到学习的不容易。没有写好的教材课程、没有画好的考点重点&#xff0c;没有一起学习的同学&#xff0c;更没有明确的学习方向和路径。 数据分析方向可以学的东西太多了&…

P18 PyTorch 感知机的梯度推导

前言这里面简单介绍一下单层感知机和多层感知机的模型参考&#xff1a;https://www.bilibili.com/video/BV17e4y1q7NG?p41一 单层感知机模型输入: k 代表网络层数&#xff0c;i 代表输入节点的编号前向传播: 权重系数k: 层数i: 前一层输入节点编号j: 当前层输出节点编号这里&a…

软件工程学习

文章目录前言软件特点分类软件工程软件危机项目管理工具总结前言 本博客仅做学习笔记&#xff0c;如有侵权&#xff0c;联系后即刻更改 科普&#xff1a; 软件 软件的定义 软件不是程序&#xff0c;而是程序、数据以及开发、使用和维护程序需要的所有文档的完整集合。 特点 …

windows 安装Qt

下载 下载地址https://download.qt.io/&#xff0c;此文已5.7.0为例子。 根据图片依次选择即可。 安装 安装过程参考另一篇文章Ubuntu 安装 Qt5.7.0即可 配置环境变量 ps&#xff1a;我就是之前没配置环境变量&#xff0c;直接使用创建项目&#xff0c;项目源码直接运行是…

CentOS7安装MariaDB步骤

文章目录1.配置MariaDB yum源2.安装MariaDBMariaDB数据库管理系统是MySQL的一个分支&#xff0c;主要由开源社区在维护&#xff0c;采用GPL授权许可。 MariaDB的目的是完全兼容MySQL&#xff0c;包括API和命令行&#xff0c;使之能轻松成为MySQL的代替品。 CentOS 6 或早期的版…

数据结构与算法基础(王卓)(11):栈的定义及其基础操作(顺序表和链表的初始化、求长度,是否为空,清空和销毁、出栈、压栈)

栈的定义&#xff1a; stack&#xff1a;一堆&#xff0c;一摞;堆&#xff1b;垛; 顺序栈和链栈的设计参考&#xff1a; 数据结构与算法基础&#xff08;王卓&#xff09;&#xff08;7&#xff09;&#xff1a;小结&#xff1a;关于链表和线性表的定义及操作_宇 -Yu的博客-C…

备考软考系统分析师-1

系统分析师教程网盘资源&#xff1a;链接: https://pan.baidu.com/s/1ekHuCJJ3o5RrW1xeMkxhdA 提取码: 6666 信息系统战略规划 信息系统开发方法&#xff1a; 结构化法 瀑布模型 原型法 自顶向下 用于需求阶段较多 面向对象 自底向上 面向服务的方法 系统建模 政府信息…

MyBatis-Plus——代码生成器(3.5.1+版本)

文章目录配置数据源配置&#xff08;DataSource&#xff09;全局配置&#xff08;GlobalConfig&#xff09;包配置&#xff08;PackageConfig&#xff09;策略配置&#xff08;StrategyConfig&#xff09;模板引擎配置&#xff08;TemplateEngine&#xff09;代码生成器测试样例…

【2】MYSQL数据的导入与导出

文章目录 MYSQL-库(相同库名称)的导入导出MYSQL-库(不同库名称)的导入导出MYSQL-表的导入导出MYSQL-表的指定查询记录导入导出前提: 客户端工具是:SQLyog MYSQL-库(相同库名称)的导入导出 1、选中指定库——右键,选择【将数据库复制到不同的主机/数据库】 2、选中指…

客户服务知识库的最佳实践7个步骤

每个公司的声誉都依赖于客户&#xff0c;如果客户因为想要购买你的产品找到你&#xff0c;但是了解到你的客户服务做的不好&#xff0c;可能也会放弃你的产品&#xff0c;就像市场营销依赖于潜在客户的关系一样&#xff0c;公司的服务部门也需要依赖于现有客户的关系&#xff0…

arxiv2017 | 用于分子神经网络建模的数据增强 SMILES Enumeration

论文标题&#xff1a;SMILES Enumeration as Data Augmentation for Neural Network Modeling of Molecules论文地址&#xff1a;https://arxiv.org/abs/1703.07076代码地址&#xff1a;https://github.com/Ebjerrum/SMILES-enumeration一、摘要摘要中明显提出&#xff1a;先指…

AI又进化了,突破性革命来了

大家好&#xff0c;我是 Jack。 2023 年&#xff0c;AI 真的杀疯了。短短不到一年的时间&#xff0c;当我们还在感慨 AI 一键生成的二次元画作精美万分的时候&#xff0c;它已经进化到了写实美照也能手到擒来的地步。 更多的效果&#xff0c;可以看刚刚发布的视频&#xff0c;…

总是跳转到国内版(cn.bing.com)?New Bing使用全攻略

你是否想要使用强大的&#xff08;被削后大嘘&#xff09;New Bing&#xff1f; 你是否已经获得了New Bing的使用资格&#xff1f; 你是否在访问www.bing.com/new时提示页面不存在&#xff1f; 你是否在访问www.bing.com时总是重定向到cn.bing.com而使用不了New Bing? New Bi…

RocketMQ之(一)RocketMQ入门

一、RocketMQ入门一、RocketMQ 介绍1.1 RocketMQ 是什么&#xff1f;1.2 RocketMQ 应用场景01、应用解耦02、流量削峰03、数据分发1.3 RocketMQ 核心组成01、NameServer02、Broker03、Producer04、Consumer1.6 运转流程1.5 RocketMQ 架构01、NameServer 集群02、Broker 集群03、…

Linux docker(03)可使用GPU渲染的x11docker实战总结

该系列文章的目的旨在之前的章节基础上&#xff0c;使用x11docker构建一个可以使用GPU的docker容器。该容器可以用于3D图形渲染/XR 等使用GPU渲染的程序调试和运行。 0 why docker 为什么非要用x11docker&#xff0c;而不是其他的docker呢&#xff1f; 因为一般的docker是不…