4. 寻找两个正序数组的中位数 Median of Two Sorted Arrays

Posted diameter

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4. 寻找两个正序数组的中位数 Median of Two Sorted Arrays相关的知识,希望对你有一定的参考价值。

Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.

The overall run time complexity should be O(log (m+n)).

 

Input: nums1 = [1,3], nums2 = [2]
Output: 2.00000
Explanation: merged array = [1,2,3] and median is 2.

 

Input: nums1 = [1,2], nums2 = [3,4]
Output: 2.50000
Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.

 

由于要求时间复杂度O(log (m+n)).就不能用暴力法

暴力法,最简单是两数据合并为一个,并排序。再查找下标 (m+n)/2 或(m+n)/2-1 ,(m+n)/2即可。

由于原数组已经有序,可以采用双指针法从两个数组依次取数据排序。

实际上,用双指针法,就不用把两个数组合并。 直接查找下标 (m+n)/2 或(m+n)/2-1 ,(m+n)/2即可。

复杂度O(m+n)。

 

复杂度O(log (m+n)),就要利用二分查找法

方法一:

 

我们要查找第k个数

 

先比较nums1[k/2-1]和nums2[k/2-1]大小,如果nums1[k/2-1]<nums2[k/2-1]

比nums1[k/2-1]小的最多有(k/2-1)+(k/2-1)= k-2个数,nums1[k/2-1]最多是第k-1大。

 

所以可以去掉nums1[k/2-1]及之前的数, 剩下的数组,第k个数仍在。

下次查找,只需要在新nums1 和nums2中查找第k=k-k/2,直到k=1。 则返回剩下数组里最小的那个。

如果查找过程中,k/2-1到达边界,则需要去掉的是实际删除的值,而不是k/2。

 

 

     public double findMedianSortedArrays(int[] nums1, int[] nums2){
        int length1 = nums1.length;
        int length2 = nums2.length;
        int totalLength = length1 + length2;
        if( totalLength % 2 == 1){
            int midIndex = totalLength /2;
            double median = getKthElement( nums1,nums2, midIndex + 1);
            return median;
        }else{
            int midIndex1 = totalLength / 2 - 1;
            int midIndex2 = totalLength / 2;
            double median =(getKthElement(nums1, nums2, midIndex1 + 1) +
                    getKthElement(nums1, nums2, midIndex2 + 1)) / 2.0;
            return median;
        }
    }
    public double getKthElement(int [] nums1, int [] nums2, int k){
        int length1 = nums1.length;
        int length2 = nums2.length;
        int index1 = 0, index2 = 0;
        while(true){
            if (index1 == length1){
                return nums2[index2 + k - 1];
            }
            if (index2 == length2){
                return nums1[index1 + k - 1];
            }
            if (k == 1){
                return Math.min(nums1[index1],nums2[index2]);
            }
            int half = k / 2;
            int newIndex1 = Math.min(index1 + half, length1) - 1;
            int newIndex2 = Math.min(index2 + half, length2) - 1;
            int pivot1 = nums1[newIndex1], pivot2 = nums2[newIndex2];
            if(pivot1 <= pivot2){
                k -= (newIndex1 - index1 + 1);
                index1 = newIndex1 + 1;
            }else{
                k -= (newIndex2 - index2 + 1);
                index2 = newIndex2 + 1;
            }
        }

    }

 

      方法二:

在任意位置i,将A划分成两部分。

在任意位置j, 将B划分成两部分。

将leftA和leftB放入一个集合left,rightA和rightB放入一个集合right

当A和B的总长度是偶数,如果len(left)=len(right)

则中位数 median = (max(left)+min(right) )/2.0

当A和B的总长度是奇数,如果len(left)=len(right)+1,则median = max(left)

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        
        int m = nums1.length;
        int n = nums2.length;
        if( m > n ){
            int [] temp = nums1;
            nums1 = nums2;
            nums2 = 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 && nums2[j - 1] > nums1[i]){
                iMin = i + 1;  //i is too small
            }else if( i > iMin && nums1[i - 1] > nums2[j]){
                iMax = i - 1;  //i is too big
            }else{
                int maxLeft = 0;
                if ( i == 0){
                    maxLeft = nums2[j-1];
                }else if ( j == 0 ){
                    maxLeft = nums1[i-1];
                }else{
                    maxLeft = Math.max(nums1[i - 1], nums2[j - 1]);
                }
                if ( (m + n) %2 == 1){
                    return maxLeft;
                }
                int minRight = 0;
                if (i == m) { minRight = nums2[j]; }
                else if (j == n) { minRight = nums1[i]; }
                else { minRight = Math.min(nums2[j], nums1[i]); }

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

时间复杂度O(log(min(m,n)))

 

参考链接:

https://leetcode.com/problems/median-of-two-sorted-arrays/

https://leetcode-cn.com/problems/median-of-two-sorted-arrays

以上是关于4. 寻找两个正序数组的中位数 Median of Two Sorted Arrays的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 4 寻找两个正序数组的中位数

Leetcode4. 寻找两个正序数组的中位数(二分)

《LeetCode-0004》 寻找两个有序数组的中位数-Median of Two Sorted Arrays

4.寻找两个正序数组的中位数

Leetcode 4. 寻找两个正序数组的中位数-困难(带图)

Hard | LeetCode 4. 寻找两个正序数组的中位数 | 二分法