Hrbust 1734 a + b + c=0【双指针】

本文解析了一道经典的算法题——寻找数组中三个数相加等于零的所有组合,并给出了解题思路及AC代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

a + b + c=0

Time Limit: 1000 MS

Memory Limit: 65535 K

 

Total Submit: 85(23 users)

Total Accepted: 21(17 users)

Rating: 

Special Judge: No

 

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");
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值