[LeetCode] 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)).

You may assume nums1 and nums2 cannot be both empty.

Example 1:

nums1 = [1, 3]
nums2 = [2]
The median is 2.0

Example 2:

nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5

题意:给出两个数组,两个数组都是升序的,输出这两个数组所有数的中位数,要求时间复杂度为O(log (m+n))

思路:这道题比较难了,时间复杂度要求比较高,如果没有时间复杂度限制的话,我们可以把两个数组合并,然后排序,这样时间复杂度为O((m+n)log (m+n));也可以像归并排序那样合并两个数组,合并之后就为有序的了,时间复杂度为O(m+n)。但这样与题目要求相比都会超时。要求中位数,如果(n+m)是奇数的话为最中间的那个数,如果为偶数的话为最中间那两个数的平均值,我么可以统一一下,无论是奇数还是偶数,我们都找第(n+m+1)/ 2个数与第(n+m+2)/ 2的平均值。

这样问题就转化为求两个升序数组第k个数的问题了,利用二分+分治的思想,我们二分k,分别在两个数组内找第k/2个数mid1,mid2,如果mid1<mid2.,就说明第k个数肯定不会在第一个数组的前k/2个数内,所以排除这一部分,我们只需在第一个数组的剩余部分和整个第二个数组内找第k-k/2个就可以了,这样分治下去,为了避免产生新的数组,这里是用两个变量i和j表示两个数组的起始位置,分治下去肯定要有终止条件,当其中一个数组不存在第k/2个数的时候,直接返回另一个数组的第k个数就行了;还有当k为1的时候,也不需在分治下去了,返回两个数组较小的一个值就行了。

C代码:

int findK(int *nums1,int nums1Size,int i,int* nums2,int nums2Size,int j,int k)
{  
    if(i >= nums1Size) return nums2[j + k - 1];
    if(j >= nums2Size) return nums1[i + k - 1];
    if(k == 1) return nums1[i] < nums2[j] ? nums1[i] : nums2[j];
    int mid1 = (i + k / 2 - 1) < nums1Size ? nums1[i + k / 2 - 1] : INT_MAX;
    int mid2 = (j + k / 2 - 1) < nums2Size ? nums2[j + k / 2 - 1] : INT_MAX;
    if(mid1 < mid2) {
        return findK(nums1,nums1Size,i + k / 2,nums2,nums2Size,j,k - k / 2);
    }
    else {
        return findK(nums1,nums1Size,i,nums2,nums2Size,j + k / 2,k - k / 2);
    }
}
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size)
{
    return ( findK(nums1,nums1Size,0,nums2,nums2Size,0,(nums1Size + nums2Size + 1) / 2) +
    findK(nums1,nums1Size,0,nums2,nums2Size,0,(nums1Size + nums2Size + 2) / 2) ) / 2.0;
}

Java代码:

public class Solution {
	public int findK(int[] nums1,int i,int[] nums2,int j,int k) {
		if(i >= nums1.length) return nums2[j + k - 1];
		if(j >= nums2.length) return nums1[i + k - 1];
		if(k == 1) return nums1[i] <= nums2[j] ? nums1[i] : nums2[j];
		int mid1 = i + k / 2 - 1 < nums1.length ? nums1[i + k / 2 - 1] : Integer.MAX_VALUE;
		int mid2 = j + k / 2 - 1 < nums2.length ? nums2[j + k / 2 - 1] : Integer.MAX_VALUE;
		if(mid1 < mid2) {
			return findK(nums1,i + k / 2,nums2,j,k - k / 2);
		}
		else {
			return findK(nums1,i,nums2,j + k / 2,k - k / 2);
		}
	}
	public double findMedianSortedArrays(int[] nums1, int[] nums2) {	
		return ( findK(nums1,0,nums2,0, ( nums1.length + nums2.length + 1) / 2) + 
				findK(nums1,0,nums2,0, ( nums1.length + nums2.length + 2) / 2) )  / 2.0;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值