小编程题之绝对和最小

来源:互联网 发布:360网络认证 编辑:程序博客网 时间:2024/06/05 05:58

给你一个数组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
原创粉丝点击