バイナリ検索:中央値を検索します。C ++

バイナリ検索:中央値を見つけます

アレイと[I]配列c [i]は数Nが与えられ、新しいアレイANSを生成します。これは、任意のI、Jのための新たな配列として定義され、iがjは=され、あるANS [] = ABS(C [I] - C [J])〕1 <= I <J <= N. この新しい配列は、次いで、中央値は、位置番号に対応するソート(1 + LEN)/ 2であり、中央値を決定し、「/」丸めあります。

入力の複数組、各入力1 N、Nを発現数、長さNの猫、猫のシーケンスの入力後に[I] <= 1E9、3 <= N <= 1E5、メジアン新しいアレイの出力

サンプル入力:
4
1 3 2 4
3
1 10 2

出力例:
1
8

アイデア:

  • 最初に考えたのは、新しい配列のすべての要素を列挙し、その後、配列をソートし、その後、場所に基づいて中央値を見つけ、確かに暴力的なソリューションです。元の数値はN有するので、減算後Cnの絶対値が存在するであろう2絶対的で暴力うち、数時間
  • アイデアは、アレイの最後の中央位置が、ゼロから(最初計算することであるので、その前の数の桁数の中央値が同じであることを特徴と我々は簡略化の中央値の性質に依存そうであっても/ 2、1 + 2 /奇数)を起動し、左境界と右境界値を定義します。左の値の範囲は、右その後見つけるために左に、中間= 1ならば、連続バイナリ検索が、見つけるために、右の表情は、次いで見つける右へ、左= 1 +真ん中。最終結果を決定するために、独自の条件に応じて右または左の最終出力です。
#include <iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[100011];
int n;
int ans;
//int ans[1000000];
int find(int mid)
{
 int count=0,temp=0;
 for(int i=0;i<n;i++)
 {
  while(temp<n&&a[temp]-a[i]<mid)//判断差值和mid的位置
  temp++;//遍历 
  count+=temp-i-1; 
 }
 if(count>=ans)//是否符合条件 
 return 1;
 else return 0;
}
int main()
{
 while(scanf("%d",&n)!=EOF)
 {
  for(int i=0;i<n;i++)
  //cin>>a[i];
  scanf("%d",&a[i]);
  int num=n*(n-1)/2;
  if(num%2==0) ans=num/2;
  else ans=num/2+1;
  sort(a,a+n);
  int l=0,m=0,r=a[n-1]-a[0];
  while(r-l>=0)
  {
   m=(r+l)/2;
   if(find(m)==1)
   r=m-1;
   else l=m+1;
   } 
   //cout<<r<<endl;
   printf("%d\n",r);
 }
 return 0;
}
  • もちろん、検索するバイナリ補間、及びUPPER_BOUND LOWER_BOUND関数計算を使用することができます。両方の機能はしている左右の開口部と部分秩序閉じ内の行動の二分法を見て。
  • それは最初のシーケンスを返すようにするためにUPPER_BOUNDが確認さよりも大きいルックアップ値のポインタである最初のシーケンスをチェック返さLOWER_BOUND 以上のルックアップポインタ値。
  • 新しいアレイの中央値の位置を決定するために使用されるメディアン中間元の配列によって算出された中央元の配列
  • アレイ[J]> [I] +中間の場合、元の値(J> I)、次いで[I]を差し引いた値を中間、中間全て計算より大きい新しい直列に形成されることを示します値、半ばは説明のいずれか大きい方の列の新しい番号、より小さい半分があれば、そうでない場合は小さな取ります。
  • 上記によれば、最終的な値を取得するには、左、右及び中央の位置を変化させます。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[1000011];
int ans;
int n;
long long num;
bool find(int mid)
{
 int count=0;
 for(int i=0;i<n;i++)
 count+=a+n-lower_bound(a+i+1,a+n,a[i]+mid);//返回第一个大于等于x[i+mid值得下标
 //count计数所有差值比mid大得数列
 return count<= num/2;//count比mid大的个数 
}
int main()
{
 while(scanf("%d",&n)!=EOF)
 {
  for(int i=0;i<n;i++)
  {
   scanf("%d",&a[i]);
   //cin>>a[i];
  }
  num=n*(n-1)/2;
  sort(a,a+n);
  int left=0,right=a[n-1];
  while(right-left>=0)
  {
   int mid=(left+right)/2;
   if(find(mid)) right=mid-1;
   else left=mid+1;
  }
  printf("%d\n",right);
  //cout<<right<<endl;
 }
 return 0;
}
  • この質問はそれピットのですか?上記のコード2に類似点を見ることができ、すべてのCINとCOUTをコメントアウトされています。TLEは、使用のscanfとprintf関数に必ずなりますcinを/アウトはい、この質問あなたは使用している場合。その理由は、キャッシュ内に配置される入力と最初のコンテンツの出力時とCIN、COUT時間であり、時間のオーバーヘッドが大きくなります。どちらのない、または同期をオフにします
  • sync_with_stdio :: IOS(偽);
    cout.tie(NULL);
    容易にポジティブなエネルギーと組み合わせます!
公開された29元の記事 ウォンの賞賛1 ビュー949

おすすめ

転載: blog.csdn.net/qq_44654498/article/details/104882700