【算法】【算法杂谈】两个排序数组中找第k小的数

news/2024/11/15 6:43:32/

目录

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

前言

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

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

问题介绍

原问题
给定两个数组arr1,arr2,求arr1和arr2合并到一起后,第k小的数是什么
如:
arr1 = [1,2,3]
arr2 = [3,4,5,6]
求第3小的数
结果为3

解决方案

原问题
参考相同长度的排序数组求上中位数的解法:

https://editor.csdn.net/md?not_checkout=1&articleId=131177400

接下来介绍如何将两个长度不相同的排序数组能够套用上面的办法
首先假设短数组长度10 [0…9]
长数组长度27 [0…26]
总长度为37

  • 如果第k小的数中k<shor.len ,也就是k <=10,那么长数组中角标大于k的部分是不会存在第k小的数的,因为后面的数至少都大于k个数,所以问题就变成了 arr1[0…k-1] 和arr2[0…k-1]之间求第k小的数问题了,套用参考即可
  • 如果第k小的数范围在 37 - 10 <= k < 37 之间时, 我们知道k后面最多只能有9个数,所以短数组都能选择,长数组可以选的范围只能是27-10到27的范围之间,问题又变成了相同长度数组求上中位数的问题,套用参考即可
  • 最后k如果都不满足上面的条件,也就是 10<k<37-10,该怎么办呢?我们假设k = 16,16前面必须有15个数,后面必须有20个数,那么现在我们看下如何补齐。前面15个数,短数组如果全补上去,还剩5个数需要长数组填,那么长数组从第5个位置开始比较,查看是否真的短数组需要补上去(短数组的最大值 < 长数组的第5个位置),如果不小于则从第6个位置开始计算
    后面20个如果将短数组全补上去还剩10个需要补,所以长数组中最多能到低16个开始往回走,我们发现长度刚好是10!直接套用公式即可。

代码编写

java语言版本

原问题:
原问题:

   /*** 二轮测试:两个排序数组中找到第k小的数* @return*/public static int findKMinFromSortArrCp1(int[] arr1, int[] arr2, int k) {if (k < 1|| arr1 == null || arr2 == null || arr1.length == 0 || arr2.length == 0|| (arr1.length + arr2.length < k)) {throw new RuntimeException("非法入参");}int[][] compareRes = compareArr(arr1, arr2);int[] shortArr = compareRes[0];int[] longArr = compareRes[1];if (k < shortArr.length) {return getUpMidFromSameLenArr(shortArr, 0, k-1, longArr, 0, k-1);}else if (k > longArr.length) {// 后面需要有几个元素int sub = (shortArr.length + longArr.length) - k;int start1 = shortArr.length - 1 - sub;int start2 = longArr.length - 1 - sub;if (longArr[start2] >= shortArr[shortArr.length - 1]) {return longArr[start2];}if (longArr[shortArr.length - 1] <= shortArr[start1]) {return longArr[shortArr.length-1];}return getUpMidFromSameLenArr(shortArr, start1+1, shortArr.length-1, longArr, start2+1, longArr.length-1);}else {int sub = (shortArr.length + longArr.length) - k;// 后面必须凑够20个int start2 = k - shortArr.length - 1;// 排除一个值否则长度不相等if (shortArr[shortArr.length - 1] <= longArr[start2]) {return longArr[start2];}else {start2++;}int end2 = longArr.length - (sub - shortArr.length) - 1;return getUpMidFromSameLenArr(shortArr, 0, shortArr.length-1, longArr, start2, end2);}}/*** 从两个数组中相同长度的子数组部分中求上中位数* @param arr1* @param start1* @param end1* @param arr2* @param start2* @param end2* @return*/private static int getUpMidFromSameLenArr(int[] arr1, int start1, int end1, int[] arr2, int start2, int end2) {int mid1 = 0;int mid2 = 0;while (start1 < end1) {// 获取中间值mid1 = (start1 + end1)/2;mid2 = (start2 + end2)/2;if (arr1[mid1] == arr1[mid2]) {return arr1[mid1];}else {// 计算长度偶数或者奇数,偶数0,奇数1int offset = ((end1 - start1 + 1) & 1) ^ 1;if (arr1[mid1] > arr2[mid2]) {// 奇数的话不需要调整数组大小直接割end1 = mid1;start2 = mid2 + offset;}else {start1 = mid1 + offset;end2 = mid2;}}}return Math.min(arr1[start1], arr2[start2]);}/*** 比较出来两个数组的长短* @param arr1* @param arr2* @return compareRes[0] 为短数组*/private static int[][] compareArr(int[] arr1, int[] arr2) {return arr1.length > arr2.length ? new int[][]{arr2, arr1} : new int[][]{arr1, arr2};}public static void main(String[] args) {System.out.println(findKMinFromSortArrCp1(new int[]{1,2,3}, new int[]{3,4,5,6}, 6));}

c语言版本

正在学习中

c++语言版本

正在学习中

思考感悟

这道题最后分析的地方为什么能够恰好是10呢?这个我仔细想了一下
首先 长数组的起始位置 k-10
结束位置,27-((37-k)-10) = k
那么结束位置 - 起始位 = 10 = 短数组长度

写在最后

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


http://www.ppmy.cn/news/352067.html

相关文章

智能血压计如何选购

血压计就是用来测量人体血压的一种仪器&#xff0c;比起人工听诊法更有效率、更有准确性&#xff0c;对于现在高血压频发的群体是非常有帮助的&#xff0c;家庭配置一个血压计是非常有必要的&#xff0c;那血压计哪种好呢?怎么选择合适的血压计呢?下面就随6108技术小编一起来…

测牛学堂:自动化软件测试python入门之函数总结(3)

函数的返回值 1函数可以有返回值&#xff0c;也可以没有返回值。 2如果没有指定&#xff0c;函数的返回值为None 3 使用return关键字可以设置函数的返回值。当函数调用以后&#xff0c;可以用变量接收函数的返回值。 4 python中的返回值可以是任意类型的数据 5 python中可以有…

中国大陆肯德基餐厅全面停用塑料吸管;可口可乐与时尚包袋品牌Kipling推出联名系列 | 美通企业日报...

今日看点&#xff1a;肯德基和必胜客在中国推出新减塑行动。比利时包袋品牌Kipling携手可口可乐推出联名系列。华扬联众与海南旅投签订战略合作协议&#xff0c;共建一流免税概念社区。博安生物完成6.82亿元战略融资。燧原科技完成C轮融资18亿。光辉国际宣布陈兆丰先生为新任中…

AndroidStudio安卓原生开发_Android扫描附近指定的蓝牙设备_通过设备名称过滤_计算距离_离扫描设备近的显示的时候放在前面---Android原生开发工作笔记128

这里直接上代码吧,我这边的应用场景是,比如我扫描附近的体重秤,注意,我扫描的时候,需要过滤,只把扫描到的特定型号的,体重秤 显示出来,比如附近的手机,血压计等都不能扫描出来.同时比如如果有两台体重秤的话,一台离的近,一台离的远,我需要把 离得近的体重秤,在显示的时候,优先…

小米变身杂货店 透支品牌还是扩展道路?

叒叒叒一次&#xff0c;小米发布了新品&#xff0c;这次是小米电视2S和小米净水器。不知道从什么时候开始&#xff0c;我们已经习惯小米这样的节奏&#xff1a;预告、预热、炒作、发布新品、预约购买……其中很多都只是很普通的产品&#xff0c;但在小米的炒作下&#xff0c;似…

深度:养老康复基础设施快速普及,新渠道+新品类红利催生医疗器械新头部品牌!

传统上主要应用于医院、养老院场景的医疗康复器械&#xff0c;正在加快进入中国亿万普通家庭。 对中国4.2亿50岁以上的中老年群体来说&#xff0c;健康始终是他们内心最大的焦虑。一旦有产品能够解决他们的健康需求&#xff0c;其强大的付费能力足以支撑许多细分方向的上市公司…

TED演讲双语演讲稿:为什么我们很难做出理性的决定?

TED演讲双语演讲稿&#xff08;精编 word打印版&#xff09; &#xff1a;为什么我们很难做出理性的决定&#xff1f; 演讲时间&#xff1a;2019年 讲者简介&#xff1a;David Asch&#xff1a;经济学家 演讲简介&#xff1a;为什么我们在明明知道的情况下还做出对健康有害的错…

2017新零售元年?总是快人一步的乐语已经走向好零售

刚刚过去的2017年对零售界来说意义非凡&#xff0c;“新零售元年”的标签让人看到了整个零售界在变革与探索上的不懈努力&#xff0c;从概念都实践&#xff0c;整个行业都在用各种各样的方式诠释各不相同的“新”。 在这股大潮中&#xff0c;三胞集团旗下的乐语无疑是一个特殊…