LeetCode-4. 寻找两个有序数组的中位数

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

思路:一:利用两指针遍历直接找出第k小值即可

二:博客:https://blog.csdn.net/yutianzuijin/article/details/11499917
将a数组切前sa片,b数组切前k-sa片,通过对a[sa-1]和b[k-sa-1]大小比较,可舍弃掉其中一部分,从而实现二分查找出第K小值 

三:博客: https://blog.csdn.net/chen_xinjia/article/details/69258706
利用对a数组切前L1片,在通过对b数组切前L2=k-L1片,通过分析比较,可实现二分查找到第K小值 

Code:

#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#include<unordered_map>
using namespace std;
typedef long long LL;

/*
class Solution {	//利用指针遍历找第K小值  O(n+m)
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        double res=0;
        int l1=nums1.size()-1,l2=nums2.size()-1,h=(l1+l2+3)/2,p;
        while(h){
        	if(l1<0){
        		p=nums2[l2--];
			}else	if(l2<0){
				p=nums1[l1--];
			}else{
				if(nums1[l1]>nums2[l2]){
					p=nums1[l1--];
				}else{
					p=nums2[l2--];
				}
			}
			--h;
		}
		res=p;
		if((nums1.size()+nums2.size())%2==0){
			if(l1<0){
				res=(res+nums2[l2])/2;
			}else	if(l2<0){
				res=(res+nums1[l1])/2;
			}else{
				if(nums1[l1]>nums2[l2]){
					res=(res+nums1[l1])/2;
				}else{
					res=(res+nums2[l2])/2;
				}
			}
		}
        return res;
    }
};
*/


/*
https://blog.csdn.net/yutianzuijin/article/details/11499917
将a数组切前sa片,b数组切前k-sa片,通过对a[sa-1]和b[k-sa-1]大小比较,可舍弃掉其中一部分,从而实现二分查找出第K小值 
*/
/* 
class Solution {	//O(log(n+m))
public:
	int len1,len2;
	int Find_K_Min(vector<int>& nums1, vector<int>& nums2, int l1, int l2, int k){
		if(l1==len1)	return nums2[k-1];
		if(l2==len2)	return nums1[k-1];
		if(k==1)	return min(nums1[l1],nums2[l2]);
		int p1=min(k/2,len1-l1),p2=k-p1;
		if(p2>len2-l2){
			p2=len2-l2;	p1=k-p2;
		}
		if(nums1[l1+p1-1]<=nums2[l2+p2-1])	return Find_K_Min(nums1,nums2,l1+p1,l2,k-p1);
		else	return Find_K_Min(nums1,nums2,l1,l2+p2,k-p2);
	}
	
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        len1=nums1.size(),len2=nums2.size();
        double res=Find_K_Min(nums1,nums2,0,0,(len1+len2+1)/2);
        if((len1+len2)%2==0)	res=(res+Find_K_Min(nums1,nums2,0,0,(len1+len2)/2+1))/2;
        return res;
    }
};
*/ 

/*
https://blog.csdn.net/chen_xinjia/article/details/69258706
利用对a数组切前l1片,在通过对b数组切前l2=k-l1片,通过分析比较,可实现二分查找到第K小值 
*/
class Solution {	//O(log(min(n,m)))
public:
	int Find_K_Min(vector<int>& nums1, vector<int>& nums2,int k){	//找第k小值 
		int len1=nums1.size(),len2=nums2.size();
		if(len1+len2<k)	return -1;
		if(!len1)	return nums2[k-1];
		if(k==1)	return min(nums1[0],nums2[0]);
		if(k==len1+len2)	return max(nums1[len1-1],nums2[len2-1]);
		if(len1>=k&&nums1[k-1]<=nums2[0])	return nums1[k-1];
		if(len2>=k&&nums2[k-1]<=nums1[0])	return nums2[k-1];
		if(len1<k&&nums1[len1-1]<=nums2[k-len1])	return max(nums1[len1-1],nums2[k-len1-1]);
		if(len2<k&&nums2[len2-1]<=nums1[k-len2])	return max(nums2[len2-1],nums1[k-len2-1]);
		int l=max(0,k-len2),r=min(len1-2,k-2),h,l1,l2,res;
		bool boo;
		while(l<=r){
			l1=h=(l+r)/2;	l2=k-l1-2;
			boo=false;
			if(nums2[l2]>nums1[l1+1]){
				boo=true;
			}else	if(nums1[l1]<=nums2[l2+1]){
				r=h;	break;
			}
			if(boo)	l=h+1;
			else	r=h-1;
		}
		return max(nums1[r],nums2[k-r-2]);
	}
	
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
    	int len1=nums1.size(),len2=nums2.size();
    	if(len1>len2){
    		swap(nums1,nums2);
    		swap(len1,len2);
		}
    	double res=Find_K_Min(nums1,nums2,(len1+len2+1)/2);
    	if((len1+len2)%2==0)	res=(res+Find_K_Min(nums1,nums2,(len1+len2)/2+1))/2;
    	return res;
    }
};


int main()
{
	int n,m,x;
	vector<int> v1,v2;
	Solution So;
	cin>>n>>m;
	for(int i=0;i<n;++i)
	{
		cin>>x;
		v1.push_back(x);
	}
	for(int i=0;i<m;++i)
	{
		cin>>x;
		v2.push_back(x);
	}
	cout<<So.findMedianSortedArrays(v1,v2)<<endl;
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用二分查找算法来解决这个问题。 首先,我们可以将两个数组合并成一个有序数组,然后求出位数。但是,这个方法的时间复杂度为 $O(m + n)$,不符合题目要求。因此,我们需要寻找一种更快的方法。 我们可以使用二分查找算法在两个数组分别找到一个位置,使得这个位置将两个数组分成的左右两部分的元素个数之和相等,或者两部分的元素个数之差不超过 1。这个位置就是位数所在的位置。 具体来说,我们分别在两个数组二分查找,假设现在在第一个数组找到了一个位置 $i$,那么在第二个数组对应的位置就是 $(m + n + 1) / 2 - i$。如果 $i$ 左边的元素个数加上 $(m + n + 1) / 2 - i$ 左边的元素个数等于 $m$ 个,或者 $i$ 左边的元素个数加上 $(m + n + 1) / 2 - i$ 左边的元素个数等于 $m + 1$ 个,则这个位置就是位数所在的位置。 具体的实现可以参考以下 Java 代码: ```java public double findMedianSortedArrays(int[] nums1, int[] nums2) { int m = nums1.length, n = nums2.length; if (m > n) { // 保证第一个数组不大于第二个数组 int[] tmp = nums1; nums1 = nums2; nums2 = tmp; int t = m; m = n; n = t; } 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 太小了,增大 i } else if (i > imin && nums1[i - 1] > nums2[j]) { imax = i - 1; // i 太大了,减小 i } else { // i 是合适的位置 int maxLeft = 0; if (i == 0) { // nums1 的左边没有元素 maxLeft = nums2[j - 1]; } else if (j == 0) { // nums2 的左边没有元素 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) { // nums1 的右边没有元素 minRight = nums2[j]; } else if (j == n) { // nums2 的右边没有元素 minRight = nums1[i]; } else { minRight = Math.min(nums1[i], nums2[j]); } return (maxLeft + minRight) / 2.0; } } return 0.0; } ``` 时间复杂度为 $O(\log\min(m, n))$。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值