2 つの順序配列の中央値を見つけるのは困難です

アルゴリズム20日

7日目

2 つの順序配列の中央値を求める

2 つの配列が与えられた場合、結合後の中央値を見つけます。必要な時間計算量は log(m+n) です。

/例 cin>>nums1=[1,3],nums2=[2]
cout<<2.00000
説明: 配列をマージして中央値を見つけます。
/

この質問は基礎の重要性を反映しています。バイナリ マージ ソートを作成するときに、マージの関数を作成しました。この質問を見たとき、私はすぐに次のように反応しました。

#include<bits/stdc++.h>
using namespace std;


vector<int> HeBing(vector<int> &a,vector<int> &b)
{
    
    
	vector<int> temp;
	int i=0,j=0;
	while(i<a.size()&&j<b.size())
	{
    
    
		if(a[i]>=b[j])
		{
    
    
			temp.push_back(b[j]);
			j++;
		}
		else
		{
    
    
			temp.push_back(a[i]);
			i++;
		}
	}
	while(i<a.size())
	{
    
    
			temp.push_back(a[i]);
			i++;
		}
	while(j<b.size())
	{
    
    
			temp.push_back(b[j]);
			j++;
	}	
	return temp;	
 } 

double Mid(vector<int> &temp)
{
    
    
	if(1&temp.size())//判断奇数还是偶数个 
		return temp[temp.size()/2];
	else
		return (double)(temp[temp.size()/2]+temp[temp.size()/2-1])/2;
	
}


int main()
{
    
    
	vector<int> a={
    
    1,2};
	vector<int> b={
    
    3,4};
	vector<int> temp=HeBing(a,b);
	printf("%0.5f",Mid(temp));
}

時間計算量がタイトルの要件を満たしていないので明日書きます
ログを見て二分法を使おうと思ったのですが、どうすれば二分化できるのでしょうか?まず、中央値は中央の数値であるため、k 番目の数値を見つけて、二分法を使用して問題を 2 つに分割するだけで済みます。画像の説明を追加してください
つまり、次のすべての要素の中で 5 番目に小さい数値を見つけます。
配列 a と b の場合、 a [k/2-1]<b[k/2-1] の場合、 k 番目に小さい数値は a[k/2-1] 以前であるため、 a[k/2-1] を除外できます。 ] とその前の数値 At most k/2+k/2-1 (b[k/2-1] とその前の数値が a[k/2-1] 未満の場合)、この時点で 2 つの要素は除外したら今 残った要素のうち、kk/2番目に大きい数を求める必要があります画像の説明を追加してください
k==1までは最後まで終わらない 偶数の場合はk+1番目に大きい数を求めれば良い

#include<bits/stdc++.h>
using namespace std;

int f(vector<int> &nums1,vector<int> &nums2,int k)
{
    
    
	int m=nums1.size();
	int n =nums2.size();
	int index1=0,index2=0;
	
	while(true)
	{
    
    
		if(index1==m)
			return nums2[index2+k-1];
		if(index2==n)
			return nums1[index1+k-1];
		if(k==1)
			return min(nums1[index1],nums2[index2]);
			
		int	i=min(index1+k/2-1,m-1);
		int j=min(index2+k/2-1,n-1);
		int pivot1=nums1[i];
		int pivot2=nums2[j];
		if(pivot1<=pivot2)
		{
    
    
			k-=i-index1+1;
			index1=i+1;
		}	
		if(pivot1>pivot2)
		{
    
    
			k-=j-index2+1;
			index2=j+1;
		}
		
	}
}
double m(vector<int> &nums1,vector<int> &nums2)
{
    
    
	int length=nums1.size()+nums2.size();
	if(length%2==1)//判断奇偶
		return f(nums1,nums2,(length+1)/2);
	else
		return (f(nums1,nums2,length/2)+f(nums1,nums2,length/2+1))/2.0;
}


int main()
{
    
    
	vector<int> a={
    
    1,2};
	vector<int> b={
    
    3,4};
	double temp=m(a,b);
	printf("%0.5f",temp);
}

時間計算量 O(log(m+n));

おすすめ

転載: blog.csdn.net/BeiWoFW/article/details/124222116