二分查找:寻找中位数
给定一个 N 个数的数组 c[i],并用这个数组生成一个新数组 ans[i]。新数组定义为对于任意的 i, j 且 i != j,均有 ans[] = abs(c[i] - c[j]),1 <= i < j <= N。试求出这个新数组的中位数,中位数即为排序之后 (len+1)/2 位置对应的数字,’/’ 为下取整。
多组输入,每次输入一个 N,表示有 N 个数,之后输入一个长度为 N 的序列 cat, cat[i] <= 1e9 , 3 <= n <= 1e5, 输出新数组的中位数
sample input:
4
1 3 2 4
3
1 10 2
sample output:
1
8
思路:
- 首先想到的解决方式肯定是暴力,先枚举出所有的新数组元素,然后给数组排序,再根据位置找到中位数的值。由于原来的数字有n,进行减法的绝对值之后就会有Cn2个数,暴力绝绝对对会超时
- 根据中位数的性质我们来进行简化,中位数的特征是它前面的数字与后面数字的个数是相同的,所以第一种想法是计算出最终数组中中位数的位置(从零开始所以偶数/2,奇数/2+1),然后定义左边界、右边界和中值。不断进行二分的查找,如果查找范围在中值左边,那么right=middle-1,再对左边进行查找;查找范围在右边,那么left=middle+1,再对右边进行查找。根据自己的结束条件来判定最终的结果是输出right还是left;
#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++;