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

【题目】

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

代码如下:

    // 由于中位数会受长度是奇偶数的影响,所以我们可以把问题转化为求
    // ((n+m+1)/2+(n+m+2)/2)/2。
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int n = nums1.length;
        int m = nums2.length;
//        return (findKthNumber(nums1, 0, n-1, nums2,0,m-1,(n+m+1)/2) +
//                findKthNumber(nums1, 0, m-1,nums2,0,m-1,(n+m+2)/2)) /2;
        return 1;
    }

    public static int findKth(int[] arr1, int[] arr2, int k) {
        if(arr1 == null || arr1.length < 1)
            return arr2[k-1];
        if(arr2 == null || arr2.length < 1)
            return arr1[k-1];
        // 注意这个函数的参数有7个,上面那个函数的参数只有3个,同名不同函数哈
        return findKth(arr1, 0, arr1.length - 1, arr2, 0, arr2.length - 1, k - 1);
    }

    public static int findKth(int[] arr1, int l1, int r1, int[] arr2, int l2, int r2, int k) {
        // 递归结束条件
        if(l1 > r1)
            return arr2[l2 + k];
        if(l2 > r2)
            return arr1[l1 + k];
        if (k == 0)// 注意,k == 0的结束条件与上面两个结束条件不能颠倒。
            return Math.min(arr1[l1],arr2[l2]);
        int md1 = l1 + k/2 < r1 ? l1 + k/2 : r1;
        int md2 = l2 + k/2 < (r2 - l1) ? l2 + k/2 : r2;
        if(arr1[md1] < arr2[md2])
            return findKth(arr1, md1 + 1, r1, arr2, l2, r2, k - k / 2 - 1);
        else if (arr1[md1] > arr2[md2])
            return findKth(arr1, l1, r1, arr2, md2 + 1, r2, k - k / 2 - 1);
        else
            return arr1[md1];//返回arr2[md2]也可以,一样的。
    }

    // 测试
    public static void main(String[] args) {
        int[] arr1 = {1, 2, 3};
        int[] arr2 = {0,4, 5, 6, 7, 8};
        System.out.println(findKth(arr1, arr2, 2));
    }

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

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

原文地址:https://www.cnblogs.com/kubidemanong/p/10579046.html

时间: 2024-07-30 09:16:19

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

求两个有序数组的中位数

这是我做的第二个leetcode题目,一开始以为和第一个一样很简单,但是做的过程中才发现这个题目非常难,给人一种“刚上战场就踩上地雷挂掉了”的感觉.后来搜了一下leetcode的难度分布表(leetcode难度及面试频率)才发现,该问题是难度为5的问题,真是小看了它!网上搜了很多答案,但是鲜见简明正确的解答,唯有一种寻找第k小值的方法非常好,在此整理一下. 首先对leetcode的编译运行吐槽一下:貌似没有超时判断,而且small和large的数据集相差很小.此题一开始我采用最笨的方法去实现,利

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

先吐槽一下,我好气啊,想了很久硬是没有做出来,题目要求的时间复杂度为O(log(m+n)),我猜到了要用二分法,但是没有想到点子上去.然后上网搜了一下答案,感觉好有罪恶感. 题目原型 正确的思路是:把问题转化一下,假设任意给一个k值,求这两个数组合并并按大小排序之后的第k个值.如此一来求中位数只是一个特例而已. 那如何搜索两个有序序列中第k个元素呢,这里又有个技巧.假设序列都是从小到大排列,对于第一个序列中前p个元素和第二个序列中前q个元素,我们想要的最终结果是:p+q等于k-1,且一序列第p个

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

二分.情况讨论 因为数组有序,所以能够考虑用二分.通过二分剔除掉肯定不是第k位数的区间.如果数组A和B当前处理的下标各自是mid1和mid2.则 1.假设A[mid1]<B[mid2], ①.若mid1+mid2+2==k(+2是由于下标是从0開始的),则 mid1在大有序数组中下标肯定小于k,所以能够排除[0,mid1].此外.B[mid2]下标大于或等于k.能够排除[mid2+1,n]: ②.若mid1+mid2+2<k,则 mid1在大有序数组中下标肯定小于k,所以能够排除[0,mid1

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

我的思路是: 用队列,  从(0,0)開始入队,每次出队的时候,选(1,0) (0,1) 之间最小的入队,假设是相等的都入队,假设入过队的就不入了,把出队的k个不同的输出来就可以 我測试了几组数据都是对的.可是可能还是会有BUG,或者我忽略的地方.以下是我的实现代码(假设有错,请大家积极指正) import java.util.LinkedList; import java.util.Queue; /** * 有两个序列 A 和 B,A=(a1,a2,...,ak),B=(b1,b2,...,b

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

中位数是把一个数的集合划分为两部分,每部分包含的数字个数相同,并且一个集合中的元素均大于另一个集合中的元素. 因此,我们考虑在一个任意的位置,将数组A划分成两部分.i表示划分数组A的位置,如果数组A包含m个元素,则划分位置有m+1种情况.因此,i的取值范围是0~m. 当i=0时,表示left_A为空:当i=m时,表示right_A为空. 同理,我们也可以划分B数组: 我们把left_A和left_B放到一个集合中,把right_A和right_B放到一个集合中. 如果想要获得中位数,要保证len

求两个有序数组的中位数或者第k小元素(转载)

http://www.cnblogs.com/TenosDoIt/p/3554479.html http://www.cnblogs.com/TenosDoIt/p/3675220.html

[LeetCode] 4. Median of Two Sorted Arrays 两个有序数组的中位数

There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). 求两个有序数组的中位数,并限制了时间复杂度O(log (m+n)),看到这个时间复杂度,自然想到用二分搜索Binary Search. 对于一个长度为n的已

寻找两个有序数组的中位数 C++实现leetcode系列(四)

给定两个大小为 m 和 n 的有序数组 nums1和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2 不会同时为空. 示例 1: nums1 = [1, 3] nums2 = [2] 则中位数是 2.0 示例 2: nums1 = [1, 2] nums2 = [3, 4] 则中位数是 (2 + 3)/2 = 2.5 这道题让我们求两个有序数组的中位数,而且限制了时间复杂度为 O(log (m+n))

两个有序数组的中位数(第k大的数)

问题:两个已经排好序的数组,找出两个数组合并后的中位数(如果两个数组的元素数目是偶数,返回上中位数). 感觉这种题目挺难的,尤其是将算法完全写对.因为当初自己微软面试的时候遇到了,但是没有想出来思路.看网上写了一堆解法,但是将思路说得非常清楚的少之又少. 有两种思路,一个是算法导论里面的,一个是求解k大元素.建议使用下面第二种思路,代码少不容易出错. 下面的内容摘自:https://blog.csdn.net/hackbuteer1/article/details/7584838 求解中位数,算