【程序设计思维与实践 Week4 作业C】TT 的神秘礼物

题目描述:

给定一个 N 个数的数组 cat[i],并用这个数组生成一个新数组 ans[i]。新数组定义为对于任意的 i, j 且 i != j,均有 ans[] = abs(cat[i] - cat[j]),1 <= i < j <= N。试求出这个新数组的中位数,中位数即为排序之后 (len+1)/2 位置对应的数字,’/’ 为下取整。

输入:

多组输入,每次输入一个 N,表示有 N 个数,之后输入一个长度为 N 的序列 cat, cat[i] <= 1e9 , 3 <= n <= 1e5 。

Sample Inpout:

4
1 3 2 4
3
1 10 2

输出:

输出新数组 ans 的中位数

Sample Output:

1
8

思路:

对于输入的cat数组,我们可以知道ans数组的大小,因此我们也可以知道中位数的位次,即小于中位数的数的个数,给定一个数P,若其位次小于中位数,则他小于中位数,若位次大于中位数,则其大于中位数。我们可以看出答案具有单调性,因此可以考虑二分的做法。我们将cat数组排序,则ans数组可由i<j,cat[j]-cat[i]求得,达到去绝对值的目的,同时我们也可求出中位数的大致范围,即数组中最后一个数减第一个数就是其最大值,且一定大于零,据此,我们也可对中位数范围进行二分,然后根据二分得到的数,再判断其与中位数的大小,若大于中位数,则二分前半部分,否则二分后半部分。
此时,剩下的问题就是给定二分得到的数据P后如何判断他与中位数的大小,即判断小于他的数有多少,因为ans[x]<P,即cat[j]-cat[i]<p(i<j)即cat[i]+P>cat[j],据此,我们遍历i,求取j的范围,可得到小于P的数据个数记作count,同时我们也求取数据等于P的个数记作temp。
记中位数位次为target,若count<target&&count+temp>=target则P即为中位数,否则若count+temp<target则P小于中位数,继续二分中位数范围后半部分,再则P大于中位数,继续二分前半部分。直到得到中位数。

代码:

#include <iostream>
#include<algorithm>
using namespace std; 
const int size=1e5+10;
int number[size];
int end(int x,int left,int n)
{//小于x的最后一个数 
	int ans=-1;
	int ll=left+1,rr=n-1;
	while(ll<=rr)
	{
		int mid=(ll+rr)>>1;
		if(number[mid]<x)
		{
			ans=mid;
			ll=mid+1;
		}
		else
			rr=mid-1;
	}
	return ans;
}
int getans(int n)
{
	int right=number[n-1]-number[0];
	int left=0;
	int sum=0;
	for(int i=1;i<n;i++)
		sum+=i;
	int target=(sum+1)/2;
	while(left<=right)
	{
		int mid=(left+right)>>1;
		int count=0,temp=0,ans=0;
		for(int i=0;i<n;i++)
		{
			int en=end((mid+number[i]),i,n);
			if(en!=-1)
			{
				count+=(en-i);	
				for(int j=en+1;j<n&&number[j]==(number[i]+mid);j++)
					temp++;			
			}
			else
				for(int j=i+1;j<n&&number[j]==(number[i]+mid);j++)
					temp++;	
		}
		if(count<target&&(count+temp)>=target)
			return mid;
		else if(count+temp<target)
			left=mid+1;
		else
			right=mid-1;	
	}
}
int main(int argc, char** argv) {
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		for(int i=0;i<n;i++)
			scanf("%d",&number[i]);
		sort(number,number+n);
		int ans=getans(n);
		printf("%d\n",ans);
	}
	return 0;
}
发布了24 篇原创文章 · 获赞 8 · 访问量 531

猜你喜欢

转载自blog.csdn.net/weixin_44034698/article/details/104875013