【题目】

给定两个有序数组arr1和arr2,已知两个数组的长度分别为 m1 和 m2,求两个数组中的第 K 小数。要求时间复杂度O(log(m1 + m2))。

【举例】

例如 arr1 = [1, 2,3],arr2 = [3,4,5,6],K = 4。

则第 K 小数为 3.

例如 arr1 = [0,1,2],arr2 = [3,4,5,7,8], K = 3;

则第 K 小数为 2.

【难度】

解答

这道题和我上次讲的那一道题是非常非常类似的:递归打卡1:在两个长度相等的排序数组中找到上中位数,如果没看过的建议先看下,只是今天的这道题比上次的那道题少难一点,原理一样。

下面我随便讲一下原理吧:采用递归的方法不断缩小 K 的,把求第 K 小元素转化为第 (K-K/2) 小元素....我举个例子吧,比较容易理解。

我们假定 arr1 = [1, 2,3],arr2 = [3,4,5,6],K = 4。

和上一道题类似(注意:这里我们假设K从0算起,也就是有第0小元素,相当于令 K = K - 1),令

mid1 = K/2 = 1。

mid2 = K/2 = 1。

此时 arr2[mid2] > arr2[mid1],那么问题转化为在数组 arr1[mid1+1...m1]和数组 arr2[0...m2] 寻找第(K-md1-1)小的元素。

不过这里需要注意的是,有可能 k/2 的值是大于 m1 或者 m2的,所以如果 k/2 > m1 或者 m2 的话,我们直接令 md1 = m1-1 或者 md2 = m2-1 就行了。

代码如下:

  1. // 由于中位数会受长度是奇偶数的影响,所以我们可以把问题转化为求
  2. // ((n+m+1)/2+(n+m+2)/2)/2。
  3. public double findMedianSortedArrays(int[] nums1, int[] nums2) {
  4. int n = nums1.length;
  5. int m = nums2.length;
  6. // return (findKthNumber(nums1, 0, n-1, nums2,0,m-1,(n+m+1)/2) +
  7. // findKthNumber(nums1, 0, m-1,nums2,0,m-1,(n+m+2)/2)) /2;
  8. return 1;
  9. }
  10. public static int findKth(int[] arr1, int[] arr2, int k) {
  11. if(arr1 == null || arr1.length < 1)
  12. return arr2[k-1];
  13. if(arr2 == null || arr2.length < 1)
  14. return arr1[k-1];
  15. // 注意这个函数的参数有7个,上面那个函数的参数只有3个,同名不同函数哈
  16. return findKth(arr1, 0, arr1.length - 1, arr2, 0, arr2.length - 1, k - 1);
  17. }
  18. public static int findKth(int[] arr1, int l1, int r1, int[] arr2, int l2, int r2, int k) {
  19. // 递归结束条件
  20. if(l1 > r1)
  21. return arr2[l2 + k];
  22. if(l2 > r2)
  23. return arr1[l1 + k];
  24. if (k == 0)// 注意,k == 0的结束条件与上面两个结束条件不能颠倒。
  25. return Math.min(arr1[l1],arr2[l2]);
  26. int md1 = l1 + k/2 < r1 ? l1 + k/2 : r1;
  27. int md2 = l2 + k/2 < (r2 - l1) ? l2 + k/2 : r2;
  28. if(arr1[md1] < arr2[md2])
  29. return findKth(arr1, md1 + 1, r1, arr2, l2, r2, k - k / 2 - 1);
  30. else if (arr1[md1] > arr2[md2])
  31. return findKth(arr1, l1, r1, arr2, md2 + 1, r2, k - k / 2 - 1);
  32. else
  33. return arr1[md1];//返回arr2[md2]也可以,一样的。
  34. }
  35. // 测试
  36. public static void main(String[] args) {
  37. int[] arr1 = {1, 2, 3};
  38. int[] arr2 = {0,4, 5, 6, 7, 8};
  39. System.out.println(findKth(arr1, arr2, 2));
  40. }

可以用迭代吗?当然可以,不过留给你自己。

下次我还会再出一道与这两道类似的题,不过,难度递增。总共有三道这种题,一定要自己手动写代码,一定要自己手动写代码,一定要自己手动写代码。

【递归打卡2】求两个有序数组的第K小数的更多相关文章

  1. 求两个有序数组的中位数或者第k小元素

    问题:两个已经排好序的数组,找出两个数组合并后的中位数(如果两个数组的元素数目是偶数,返回上中位数). 设两个数组分别是vec1和vec2,元素数目分别是n1.n2. 算法1:最简单的办法就是把两个数 ...

  2. 求两个有序数组的中位数(4. Median of Two Sorted Arrays)

    先吐槽一下,我好气啊,想了很久硬是没有做出来,题目要求的时间复杂度为O(log(m+n)),我猜到了要用二分法,但是没有想到点子上去.然后上网搜了一下答案,感觉好有罪恶感. 题目原型 正确的思路是:把 ...

  3. (算法)两个有序数组的第k大的数

    题目: 有两个数组A和B,假设A和B已经有序(从大到小),求A和B数组中所有数的第K大. 思路: 1.如果k为2的次幂,且A,B 的大小都大于k,那么 考虑A的前k/2个数和B的前k/2个数, 如果A ...

  4. 计算两个有序数组的第K大数(转)

    传统解法,最直观的解法是O(m+n).直接merge两个数组,然后求第K大的数字. 如果想要时间复杂度将为O(log(m+n)).我们可以考虑从K入手.如果我们每次能够删除一个一定在第K个元素之前的元 ...

  5. [LeetCode]Median of Two Sorted Arrays 二分查找两个有序数组的第k数(中位数)

    二分.情况讨论 因为数组有序,所以能够考虑用二分.通过二分剔除掉肯定不是第k位数的区间.如果数组A和B当前处理的下标各自是mid1和mid2.则 1.假设A[mid1]<B[mid2], ①.若 ...

  6. 算法-求两个有序数组两两相加的值最小的K个数

    我的思路是: 用队列,  从(0,0)開始入队,每次出队的时候,选(1,0) (0,1) 之间最小的入队,假设是相等的都入队,假设入过队的就不入了,把出队的k个不同的输出来就可以 我測试了几组数据都是 ...

  7. Median of Two Sorted 求两个有序数组的中位数

    中位数是把一个数的集合划分为两部分,每部分包含的数字个数相同,并且一个集合中的元素均大于另一个集合中的元素. 因此,我们考虑在一个任意的位置,将数组A划分成两部分.i表示划分数组A的位置,如果数组A包 ...

  8. 【medium】4. Median of Two Sorted Arrays 两个有序数组中第k小的数

    There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...

  9. leetcode题目4.寻找两个有序数组的中位数(困难)

    题目描述: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和  ...

随机推荐

  1. JS 小技巧整理

    一.javascript中调用函数并不一定严格执行指定的参数个数.(函数定义时的参数个数和调时指定的参数个数并不一定要相等) function showInfo(arg1) { var defindl ...

  2. 2018山东省ACM省赛G题-Game

    Alice and Bob are playing a stone game. There are n piles of stones. In each turn, a player can remo ...

  3. Maven项目管理工具

    Maven项目管理工具 白面郎君 Svn eclipse maven量级 1 Maven的简介 1.1 什么是maven 是apache下的一个开源项目,是纯java开发,并且只是用来管理java项目 ...

  4. 设计模式的征途—17.模板方法(Template Method)模式

    在现实生活中,很多事情都需要经过几个步骤才能完成,例如请客吃饭,无论吃什么,一般都包含:点单.吃东西.买单等几个步骤,通常情况下这几个步骤的次序是:点单=>吃东西=>买单.在这3个步骤中, ...

  5. spring cloud 入门系列七:基于Git存储的分布式配置中心

    我们前面接触到的spring cloud组件都是基于Netflix的组件进行实现的,这次我们来看下spring cloud 团队自己创建的一个全新项目:Spring Cloud Config.它用来为 ...

  6. Object类的toString()方法总结

    1.java语言很多地方会默认调用对象的toString方法. 注:如果不重写toString方法,将会 使用Object的toString方法,其逻辑为  类名@散列码,toString方法是非常有 ...

  7. POI处理Excel中各种日期格式问题

    前不久写过一篇随笔<EXCEL解析之终极方法WorkbookFactory>,提到使用WorkbookFactory来处理Excel文件数据,最近发现一个问题就是这个办法不能很好的处理各种 ...

  8. 数据结构(C++)之Double Linked List实践

    //double linked list (type int),the position starts from 0 #include <iostream> using namespace ...

  9. Web测试——翻页功能测试用例

    参考:https://wenku.baidu.com/view/e6462707de80d4d8d15a4f1e.html?rec_flag=default&mark_pay_doc=2&am ...

  10. Django 的数据库查询

    class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def _ ...