004 两个排序数组的中位数

LeetCode第四题 两个排序数组的中位数

有两个大小为 m 和 n 的排序数组 nums1 和 nums2 。
请找出两个排序数组的中位数并且总的运行时间复杂度为 O(log (m+n)) 。
示例 1:

nums1 = [1, 3]
nums2 = [2]

中位数是 2.0

示例 2:
nums1 = [1, 2]
nums2 = [3, 4]

中位数是 (2 + 3)/2 = 2.5

方法一

解题思路

对于这道题,难点在于运行时间复杂度,使用排序算法,将两个数值合并排序,在选出中位数的方法,显然不符合时间复杂度的要求,因此,我们参考了网址中的解题方法,时间复杂度符合要求。
首先,确保两个有序数组的长度m<=n,如果不是这样,交换两个数组位置,这对我们以后的讨论,带来简便。
使用变量i和j分别代表了数组A和数组B的下标,其中j=(m+n+1/2)-i,之所以这样做,是因为中位数将两个数组分成长度相等的两部份,也就是说数组A的左半部分加上数组B的左半部分等于,数组A的右半部分加上数组B的右半部分。
另外使用了iMin和iMax表示了数组A的下标i的取值范围,使用一个while循环,不断的更新i和j的值,从而找到中位数的下标位置。
更新下标时,通常会遇到三种情况:
1. 下标i的值太小了。此时,(i < m && j > 0 && B[j-1] > A[i]) 也就是说数组B的第j-1个值(左侧)都比数组A的第i个值(右侧)大,此时需要增大i的值。
2. 下标i的值太大了。此时,(i > 0 && j < n && A[i-1]> B[j]) 也就是说数组A的中位数左侧的大于数组B的中位数右侧的值了,此时需要减小i的值。
3. 除了上述的两种情况外,此时的下标i和j刚刚好。

在情况三下,需要进一步讨论中位数的取值,此时又分两种情况:
-. m+n是奇数。只要找到左侧最大值即可。
-. m+n是偶数。找到左侧最大值和右侧最小值,返回平均值。

Java

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m = nums1.length, n = nums2.length;
        if (m > n)
            return findMedianSortedArrays(nums2, nums1);/// 保证m<=n
        int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;
        while (iMin <= iMax) {
            int i = (iMax + iMin) / 2;
            int j = halfLen - i;
            if (i < m && j > 0 && nums2[j - 1] > nums1[i]) {
                iMin = iMin + 1;
            } else if (i > 0 && j < n && nums1[i - 1] > nums2[j]) {
                iMax = iMax - 1;
            } else {
                double 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;
                double minRight = 0;
                if (i == m) {
                    minRight = nums2[j];
                } else if (j == n) {
                    minRight = nums1[i];
                } else {
                    minRight = Math.min(nums1[i], nums2[j]);
                }
                return (maxLeft + minRight) / 2.0;
            }
        }
        return 0.0;
    }

Python

class Solution(object):
    def findMedianSortedArrays(self, A, B):
        m, n = len(A), len(B)
        if (m > n):
            return Solution().findMedianSortedArrays(B, A)
        iMin, iMax, halfLen = 0, m, int((m + n + 1) / 2)
        while iMin <= iMax:
            i = int((iMax + iMin) / 2)
            j = int(halfLen - i)
            if i < m and j > 0 and B[j - 1] > A[i]:
                iMin = iMin + 1
            elif i > 0 and j < n and A[i - 1] > B[j]:
                iMax = iMax - 1
            else:
                if i == 0:
                    maxLeft = B[j - 1]
                elif j == 0:
                    maxLeft = A[i - 1]
                else:
                    maxLeft = max(A[i - 1], B[j - 1])
                if (m + n) % 2 == 1:
                    return maxLeft

                if i == m:
                    minRight = B[j]
                elif j == n:
                    minRight = A[i]
                else:
                    minRight = min(A[i], B[j])
                return (maxLeft + minRight) / 2.0

C++


class Solution
{
public:
    double findMedianSortedArrays(vector<int>& A, vector<int>& B)
    {
        int m = A.size(), n = B.size();
        if(m>n)return findMedianSortedArrays(B, A);
        int iMin = 0, iMax = m, halfLen = (m+n+1)/2;
        while(iMin<=iMax)
        {
            int i = (iMin+iMax)/2;
            int j = halfLen - i;
            if(i<m&&j>0&& B[j-1]>A[i])
            {
                iMin = iMin + 1;
            }
            else if(i>0&&j<n&&A[i-1]>B[j])
            {
                iMax = iMax - 1;
            }
            else
            {
                double maxLeft = 0;
                if(i==0)
                {
                    maxLeft=B[j-1];
                }
                else if(j==0)
                {
                    maxLeft=A[i-1];
                }
                else
                {
                    maxLeft=max(A[i-1],B[j-1]);
                }
                if((m+n)%2==1)return maxLeft;

                double minRight = 0;
                if(i==m)
                {
                    minRight = B[j];
                }
                else if(j==n)
                {
                    minRight=A[i];
                }
                else
                {
                    minRight = min(A[i],B[j]);
                }
                return (maxLeft+minRight)/2.0;
            }
        }
        return 0.0;
    }
};

方法二

本方法更加简便有效。因为数组A和数组B都是排序好的,因此我们使用一个数组C,有序的将A和B放进C中,最终取出C中的中位数,超级简单。

java

    public double findMedianSortedArrays(int[] A, int[] B) {
        int m = A.length, n = B.length;
        int[] C = new int[m+n];
        int i=0,j=0;
        while(true){
            if(i>=m||j>=n) break;
            if(A[i]<B[j]){
                C[i+j]=A[i];
                i++;
            }else{
                C[i+j]=B[j];
                j++;
            }
        }
        if(i==m){
            for(int k=j;k<n;k++){
                C[i+k]=B[k];
            }
        }else{
            for(int k=i;k<m;k++){
                C[j+k]=A[k];
            }
        }
        if((m+n)%2==1){
            return C[(m+n)/2];
        }else{
            return (C[(m+n)/2-1]+C[(m+n)/2])/2.0;
        }
    }

C++

    double findMedianSortedArrays(vector<int>& A, vector<int>& B)
    {
        int m = A.size(), n = B.size();
        vector<int>C = vector<int>();
        int i=0,j=0;
        while(true)
        {
            if(i>=m||j>=n)break;
            if(A[i]<B[j])C.push_back(A[i++]);
            else C.push_back(B[j++]);
        }
        if(i==m)
            for(int k=j; k<n; k++)
                C.push_back(B[k]);
        else
            for(int k=i; k<m; k++)
                C.push_back(A[k]);
        if((m+n)%2==1) 
            return C[(m+n)/2];
        else 
            return (C[(m+n)/2-1]+C[(m+n)/2])/2.0;
    }

python

class Solution(object):
    def findMedianSortedArrays(self, A, B):
        m, n = len(A), len(B)
        i, j = 0, 0
        C = [0 for x in range(0, m+n)]
        while True:
            if (i >= m or j >= n):
                break;
            if (A[i] < B[j]):
                C[i+j] = A[i]
                i = i+1
            else:
                C[i+j] = B[j]
                j = j+1
        if (i == m):
            for k in range(j, n):
                C[i+k] = B[k]
        else:
            for k in range(i, m):
                C[j+k] = A[k]
        if ((m+n)%2==1):
            return C[int((m+n)/2)]
        else:
            return (C[int((m+n)/2-1)]+C[int((m+n)/2)])/2.0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值