前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【递归打卡2】求两个有序数组的第K小数

【递归打卡2】求两个有序数组的第K小数

作者头像
帅地
发布2019-03-30 12:26:53
1.6K0
发布2019-03-30 12:26:53
举报
文章被收录于专栏:苦逼的码农苦逼的码农

【题目】

给定两个有序数组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 就行了。

代码如下:

代码语言:javascript
复制
 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
11    public static int findKth(int[] arr1, int[] arr2, int k) {
12        if(arr1 == null || arr1.length < 1)
13            return arr2[k-1];
14        if(arr2 == null || arr2.length < 1)
15            return arr1[k-1];
16        // 注意这个函数的参数有7个,上面那个函数的参数只有3个,同名不同函数哈
17        return findKth(arr1, 0, arr1.length - 1, arr2, 0, arr2.length - 1, k - 1);
18    }
19
20    public static int findKth(int[] arr1, int l1, int r1, int[] arr2, int l2, int r2, int k) {
21        // 递归结束条件
22        if(l1 > r1)
23            return arr2[l2 + k];
24        if(l2 > r2)
25            return arr1[l1 + k];
26        if (k == 0)// 注意,k == 0的结束条件与上面两个结束条件不能颠倒。
27            return Math.min(arr1[l1],arr2[l2]);
28        int md1 = l1 + k/2 < r1 ? l1 + k/2 : r1;
29        int md2 = l2 + k/2 < (r2 - l1) ? l2 + k/2 : r2;
30        if(arr1[md1] < arr2[md2])
31            return findKth(arr1, md1 + 1, r1, arr2, l2, r2, k - k / 2 - 1);
32        else if (arr1[md1] > arr2[md2])
33            return findKth(arr1, l1, r1, arr2, md2 + 1, r2, k - k / 2 - 1);
34        else
35            return arr1[md1];//返回arr2[md2]也可以,一样的。
36    }
37
38    // 测试
39    public static void main(String[] args) {
40        int[] arr1 = {1, 2, 3};
41        int[] arr2 = {0,4, 5, 6, 7, 8};
42        System.out.println(findKth(arr1, arr2, 2));
43    }

`

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 帅地玩编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 【题目】
  • 【举例】
  • 【难度】
  • 解答
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档