a + b + c=0 | ||||||
| ||||||
Description | ||||||
There is a sequence A containing n integers. How many combinations can make a + b + c = 0 (a∈A, b∈A, c∈A). | ||||||
Input | ||||||
There are multiple test cases. The first line is an positive integer T standing for the number of test cases. For each test case, the first line is one integer n. The second line are n integers a1, a2, ..., an, separated by space. (1<=n<=5000,|ai|<=100 000 000) | ||||||
Output | ||||||
For each test case, output all the combination satisfied a + b + c=0, by lexicographical order. If there doesn't exit, output "<empty>" in one line. Output a blank line after each test case. | ||||||
Sample Input | ||||||
2 6 -1 0 1 2 -1 -4 6 1513 5031 5031 -1582 4769 10 | ||||||
Sample Output | ||||||
-1 -1 2 -1 0 1
<empty> | ||||||
Source | ||||||
哈理工2013春季校赛 - 现场赛(热身) |
题目大意:
输出字典序升序条件下的没有重复的所有三元组(a,b,c),使得a+b+c==0
思路:(一个煞笔的思路构建过程........)
1、首先,字典序升序输出同时也提醒了我们排序来做,其实即使开了spj没有提醒排序,我们也能很容易想到排序吧...............那么,排序是首要步骤
2、看到N是5000.首先我们最无脑的方式就是N^3枚举,显然会超时,最简单的也是最好想的就是N^2LogN,先对序列排序,之后N^2枚举a,b,然后因为序列是递增的,所以a+b+编号为mid的数是递增的,所以可以二分查找,时间复杂度O(N^2LogN)如果N==1000其实还是有点希望过掉的,然而N==5000,还是光荣的TLE了
3、然后想办法将N^2LogN再降掉一些就差不多了,然后想到N^2枚举a,b,用Hash表查-(a+b),能够达到N^2的时间复杂度,只可惜,题目不保证数据不重复,反而样例都已经告诉你会有重复的数据出现了,去重去了半天,最后还是投降了。
4、最后能想到的办法就是双指针了,一层for枚举a,然后定义两个指针ii,jj,因为序列是递增的,所以:
①如果a+num【ii】+num【jj】>0 jj--;
②如果a+num【ii】+num【jj】<0 ii++;
③如果a+num【ii】+num【jj】==0;jj--,并处理相同解(去重解)。ii++,
T T 为什么我没有直接向用指针法来做....................
Ac代码:
#include<stdio.h>//N^2LogN TLE
#include<algorithm>
#include<string.h>
using namespace std;
int a[5005];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
int flag=0;
sort(a,a+n);
for(int i=0;i<n;i++)
{
if(i!=0&&a[i]==a[i-1])continue;
int ii=i+1;
int jj=n-1;
while(ii<=jj&&ii<n&&jj>i+1)
{
int tmp=a[ii]+a[jj]+a[i];
if(tmp>0)
{
jj--;
}
else if(tmp<0)
{
ii++;
}
else
{
if(ii!=i&&ii!=jj&&ii!=jj)
{
flag=1;
printf("%d %d %d\n",a[i],a[ii],a[jj]);
}
jj--;
while(a[ii]==a[ii+1]&&ii<n)ii++;
ii++;
}
}
}
if(flag==0)
{
printf("<empty>\n");
}
printf("\n");
}
}