Leetcode:Question4--Median of Two Sorted Arrays

题目描述

在这里插入图片描述

解法

这道题目假如采取最普通的做法,即为将两个数组结合在一起,再进行排序,然后取出直接取出中位数即可。排序的算法最优复杂度为 O(nlogn),而取出中位数的复杂度为O(n),遍历两个数组的复杂度也是O(n),所以整个算法的复杂度为O(nlogn),明显超过题目的要求,不可采取

不过最后在accepted列表里发现有人采取这种方法然后LeetCode给过的。
这里附上这种方法的代码

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int[] nums = new int[nums1.length + nums2.length];
        int p1 =0;
        int p2 =0;
        int i;
        for(i =0;p1<nums1.length && p2<nums2.length && i<nums.length;i++){
            if(nums1[p1]> nums2[p2]){
                nums[i] = nums2[p2];
                p2++;
            }else{
                nums[i] = nums1[p1];
                p1++;
            }
        }
        while(p1< nums1.length){
            nums[i] = nums1[p1];
            p1++;
            i++;
        }
         while(p2< nums2.length){
            nums[i] = nums2[p2];
            p2++;
            i++;
        }
        if(nums.length%2==1){
            return nums[nums.length/2];
        }
        
            return (nums[nums.length/2] + nums[nums.length/2-1] )/2.0;
    }
}

接着思考第二种方法。要达到log,必须采取二分。一开始的思路是取num1数组的中位数a,接着取num2数组的中位数b,那么中位数必然在a 和 b中间。但只能确定这一步的范围。
举例说明,假如a < b, 那么中位数在a, b之间,假如你把小于a的部分砍掉,把大于b的部分砍掉,那么此时数的奇偶性就会改变,你最后求得的中位数必然会有偏差。
因此不可以采用丢弃的方法来解决这道题
在这里插入图片描述


最后采取了答案的方法
假如将两个数组分成left part和right part
在这里插入图片描述

然后满足
在这里插入图片描述

那么中位数就可以通过
在这里插入图片描述

需要满足的条件即为
在这里插入图片描述

那么如何找到这个i呢,即通过二分法搜索就能够达到O(logn)的复杂度
搜索过程中一共有一下三种情况

在这里插入图片描述

根据大小,决定二分法取中值的方向
找到i之后,就能够确定中值

代码如下

class Solution {
    public double findMedianSortedArrays(int[] A, int[] B) {
        int m = A.length;
        int n = B.length;
        if (m > n) { // to ensure m<=n
            int[] temp = A; A = B; B = temp;
            int tmp = m; m = n; n = tmp;
        }
        int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;
        while (iMin <= iMax) {
            int i = (iMin + iMax) / 2;
            int j = halfLen - i;
            if (i < iMax && B[j-1] > A[i]){
                iMin = i + 1; // i is too small
            }
            else if (i > iMin && A[i-1] > B[j]) {
                iMax = i - 1; // i is too big
            }
            else { // i is perfect
                int maxLeft = 0;
                if (i == 0) { maxLeft = B[j-1]; }
                else if (j == 0) { maxLeft = A[i-1]; }
                else { maxLeft = Math.max(A[i-1], B[j-1]); }
                if ( (m + n) % 2 == 1 ) { return maxLeft; }

                int minRight = 0;
                if (i == m) { minRight = B[j]; }
                else if (j == n) { minRight = A[i]; }
                else { minRight = Math.min(B[j], A[i]); }

                return (maxLeft + minRight) / 2.0;
            }
        }
        return 0.0;
    }
}

最后复杂度为O(log(min{m, n}))。只需要选择数量较小的一个数组进行搜索即可

猜你喜欢

转载自blog.csdn.net/huangbx_tx/article/details/82912185
今日推荐