给你一个数组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,即这种方法的时间复杂度是
。