小编程题之绝对和最小

30 篇文章 0 订阅

给你一个数组A[n],请你计算出ans=min(|A[i]+A[j]|)(0<=i,j<n).< span="" style="box-sizing: border-box;">

例如:A={1, 4, -3},

则:

|A[0] + A[0]| = |1 + 1| = 2.

|A[0] + A[1]| = |1 + 4| = 5.

|A[0] + A[2]| = |1 + (-3)| = 2.

|A[1] + A[1]| = |4 + 4| = 8.

|A[1] + A[2]| = |4 + (-3)| = 1.

|A[2] + A[2]| = |(-3) + (-3)| = 6.

所以ans=1.

输入描述:

有多组测数数据,每组数据有两行,第一行包含一个正整数n(0<n<=100000),第二行包含n个整数,分别表示a[0],a[1],a[2],....,a[n-1],(|a[i]|<2^30)。 <="" p="" style="box-sizing: border-box;">

输入以文件结束。

输出描述:

对于每组数据,输出相应的答案。

原题http://student.csdn.net/mcs/question_detail/587。

一开始使用的是最原始的时间复杂度最大的一种算法,类似于穷举。用两个for循环完成,但是时间使用太长,没通过。

然后借鉴了网友http://blog.csdn.net/zhangxiangDavaid/article/details/25251505的算法来完成

代码如下


<span style="color:#666666;">#include<iostream>
#include<fstream>
#include<vector>
#include<algorithm>
using namespace std;

int main()
{
	
	vector <int> num;
	int n,i,j,buff,tmp;
	unsigned int min,min_tmp;
	//freopen("test.txt","r",stdin);
	while(cin>>n)
	{
		
		min=0;
		for(i=0;i<n;i++)
		{
			cin>>buff;
			num.push_back(buff);
			if(buff==0) 
				min=1;
		}
		
		//for(i=0;i<num.size();i++)
		//{
		//	cout<<num[i]<<" ";
		//}
		//cout<<endl;
		if(min == 1)
		{
			cout<<min-1<<endl;
		}
		else
		{	
			</span><span style="color:#ff0000;">n=num.size();
			sort(num.begin(),num.end());
			tmp=num[0]+num[n-1];
			min=abs(tmp);
			i=0;
			j=n-1;
			//cout<<" i j "<<i<<" "<<j<<endl;
			while(1)
			{
				if(i==j)
					break;
				if(tmp==0)
				{
					min=0;
					break;
				}
				else if(tmp>0)
				{
					j--;
				}
				else
				{
					i++;
				}
				tmp=num[i]+num[j];
				min_tmp=abs(tmp);
				if(min>min_tmp)
					min=min_tmp;	</span><span style="color:#666666;">				
				
			}
			/*
			min=abs(num[0]+num[0]);
			for(i=0;i<num.size();i++)
			{
				for(j=i;j<num.size();j++)
				{
					tmp=abs(num[i]+num[j]);
					if(min > tmp)
						min = tmp;
				}
			}
			*/
			
		    cout<<min<<endl;
			
		}
		num.erase(num.begin(),num.end());
		
	}


}</span>
------------------------------------------------------------以下来源于上面地址链接的网友算法-------------------------------------------------------------

    题目讲的很罗嗦,简单讲就是:从一数组中找出两个元素和的绝对值最小的,给出这个最小值,可以是同一个数。

   先看清题目,我们得明白找的是和的绝对值最小者,并且可以是同一个数。看到无序的就应想到先排序,肯定优先选快速排序。那排序之后呢……

排序之后我们可以:


使用两个指向首尾的指针i,j(这里的指针并不是c语言里的指针类型,但有着异曲同工的妙处)。

我们对 a[i]+a[j] 进行判断:(我们的目标是让 a[i]+a[j] 向0靠近)

如果 a[i]+a[j]>0,则表明a[j]过大,则应该 j--;

如果 a[i]+a[j]<0,则表明a[i]过小,则应该 i++;

如果 a[i]+a[j]=0,则不用再找了,因为没有比零更小的绝对值了。

重复这三个判断,直到i和j相等。(在移动指针的过程中,及时更新最小值)

讨论:

    有人说不用排序,用枚举法,这是可行的,不过枚举的集合个数是,其中是数组中两个不同元素和的个数,n是同一元素和的个数,当n很大的时候,效果不能让人满意。=n(n-1)/2+n=n(n+1)/2,即这种方法的时间复杂度是








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值