求两个有序数组的中位数(第K大)Leetcode 04 Apare_xzc

寻找两个有序数组的中位数

2020.8.5


题目链接:Leetcode 04

思路一:直接归并,时间复杂度O(m+n),空间O(m+n)

int getKth2(int * a,int * b,int m,int n,int k) {
	assert(k>0&&k<=m+n&&n>=0&&m>=0);
	vector<int> c(m+n);
	int p1 = 0, p2 = 0,index = 0;
	while(p1<m||p2<n) {
		if(p2==n||(p1<m&&a[p1]<=b[p2])) c[index++] = a[p1++];
		else c[index++] = b[p2++];
	} 
	return c[k-1];
}

思路二:用归并的思想,不开额外数组,用两个指针向前移动,O(m+n), O(1)

int getKth1(int * a,int * b,int m,int n,int k) {
	assert(m+n>=k&&k>0);
	int p1 = 0, p2 = 0, cnt = 0;
	if(m==0) return b[k-1];
	if(n==0) return a[k-1];
	while(cnt<k) {
		if(p2==n||(p1<m&&a[p1]<=b[p2])) ++p1;
		else ++p2;
		++cnt;
	}
	return max(a[p1-1],b[p2-1]);
}

思路三:用二分的思想

-每次取A[k/2-1], B[k/2-1], 如果 A[k/2-1] > B[k/2-1],那么A[0]到A[k/2-1]一定在前K大,数组A删除前面A[0]到A[k/2-1]的元素,K减去相应的个数。向下递归

  • 如果A长度为0,直接返回B[k-1], B同理
  • A,B都不空,且K = 1,直接返回min(A[0],B[0])
  • 如果k/2-1越界,那么只能取最后一个
int getKth(int * a,int * b,int m,int n,int k) {
	assert(k>=0&&k<=m+n&&m>=0&&n>=0);
	int id1 = 0,id2 = 0;
	while(true) {
		if(id1==m) return b[id2+k-1];
		if(id2==n) return a[id1+k-1];
		if(k==1) return min(a[id1],b[id2]);
		int newid1 = min(id1+k/2-1,m-1);
		int newid2 = min(id2+k/2-1,n-1);
		if(a[newid1]<=b[newid2]) {
			k -= newid1-id1+1;
			id1 = newid1 + 1;
		} else {
			k -= newid2-id2+1;
			id2 = newid2 + 1; 
		} 
	}	
}

测试

#include <bits/stdc++.h>
using namespace std;
int a[100],b[100];
int getKth(vector<int> v1,vector<int> v2,int k) {
	int m = v1.size();
	int n = v2.size();
	assert(k>0&&k<=m+n);
	int id1 = 0, id2 = 0;
	while(true) {
		if(id1==m) return v2[id2+k-1];
		if(id2==n) return v1[id1+k-1];
		if(k==1) return min(v2[id2],v1[id1]);
		int len = k/2-1;
		int newid1 = min(m-1,id1+len);	
		int newid2 = min(n-1,id2+len);
		if(v1[newid1]<=v2[newid2]) {
			k -= newid1-id1+1;
			id1 = newid1+1;	
		} else{
			k -= newid2-id2+1;
			id2 = newid2+1;
		}
	} 
}
int getKth1(int * a,int * b,int m,int n,int k) {
	assert(m+n>=k&&k>0);
	int p1 = 0, p2 = 0, cnt = 0;
	if(m==0) return b[k-1];
	if(n==0) return a[k-1];
	while(cnt<k) {
		if(p2==n||(p1<m&&a[p1]<=b[p2])) ++p1;
		else ++p2;
		++cnt;
	}
	return max(a[p1-1],b[p2-1]);
}
int getKth2(int * a,int * b,int m,int n,int k) {
	assert(k>0&&k<=m+n&&n>=0&&m>=0);
	vector<int> c(m+n);
	int p1 = 0, p2 = 0,index = 0;
	while(p1<m||p2<n) {
		if(p2==n||(p1<m&&a[p1]<=b[p2])) c[index++] = a[p1++];
		else c[index++] = b[p2++];
	} 
	for(int i=0;i<index;++i)
		cout<<c[i]<<" ";cout<<endl;
	return c[k-1];
}

int main(void) {
	srand(time(NULL));
	int m = rand()%7+5;
	int n = rand()%7+5;
	for(int i=0;i<m;++i) a[i] = rand()%59;
	for(int i=0;i<n;++i) b[i] = rand()%59;
	sort(a,a+m);
	sort(b,b+n);
	vector<int> v1,v2;
	for(int i=0;i<m;++i) v1.push_back(a[i]);
	for(int j=0;j<n;++j) v2.push_back(b[j]);
	for(int k=1;k<=n+m;++k) {
		cout<<getKth2(a,b,m,n,k)<<" ";
		cout<<getKth1(a,b,m,n,k)<<" ";
		cout<<getKth(v1,v2,k)<<endl;
	}
	return 0;
} 

求中位数

class Solution {
public:
    int getKth(const vector<int>& v1,const vector<int>& v2,int k) {
        int m = v1.size();
        int n = v2.size();
        int id1 = 0, id2 = 0;
        while(true) {
            if(id1==m) return v2[id2+k-1];
            if(id2==n) return v1[id1+k-1];
            if(k==1) return min(v2[id2],v1[id1]);
            int len = k/2-1;
            int newid1 = min(m-1,id1+len);	
            int newid2 = min(n-1,id2+len);
            if(v1[newid1]<=v2[newid2]) {
                k -= newid1-id1+1;
                id1 = newid1+1;	
            } else{
                k -= newid2-id2+1;
                id2 = newid2+1;
            }
        } 
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int len1 = nums1.size(), len2 = nums2.size();
        int tot = len1+len2;
        if((tot)&1) {
            return getKth(nums1,nums2,tot/2+1);
        }
        else return (getKth(nums1,nums2,tot/2)+getKth(nums1,nums2,tot/2+1))*0.5;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_40531479/article/details/107809595