lintcode 三数之和(双指针)法

题目链接:三数之和 

 因为要求使a+b+c=0的三元组,因此先将数组s进行排序

sort(A.begin(),A.end());

 又因为不能使结果包含重复的三元组,所以定义一个set判断此三元组是否在之前出现过

//用于接收和=0的三元组
pair<pair<int,int>,int> x;

//储存三元组
set<pair<pair<int,int>>> mp;

 之后定义left,right,让left=i+1,right = 数组长度-1,之后对A[i]+A[left]+A[right]的和进行判断,如果大于零则让right的值向前移一位right-1,如果小于零则令left+1,当left>=right时结束此次循环,进行下次循环,如果A[right] = A[right-1],为了防止出现重复解,可以令right-1,直到不相等为止,对于left一样,让left+1直到不相等。

 完整代码:

class Solution {
public:
    /**
     * @param numbers: Give an array numbers of n integer
     * @return: Find all unique triplets in the array which gives the sum of zero.
     */
    vector<vector<int>> threeSum(vector<int> &A) {
        // 求数组的长度
        int len = A.size();

        //储存三元组
        vector<vector<int>> ans;

        //判断三元组是否出现过
        set<pair<pair<int,int>,int>> flag;

        //保存三元组用于
        pair<pair<int,int>,int> x;

        //对数组进行排序
        sort(A.begin(),A.end());
        
        //如果数组长度小于三,直接返回ans,因为不可能有三个数相加等于0
        if(len < 3)
            return ans;

        //left为左指针,right为右指针
        int left,right;
        for(int i = 0;i<len;i++)
        {
            //让left = i的下一位
            left = i+1;
            //right从最右边开始计算
            right = len-1;

            //当A[i]大于0时表名i的后面全为大于0的值因此不可能出现等于0的情况,直接返回ans即可
            if(A[i]>0)
                return ans;
            
            //当三数之和不为0时进行判断
            while((A[i]+A[left]+A[right])!=0)
            {

                //如果三数之和>0表名右指针值太大,令其左移
                while((A[i]+A[left]+A[right])>0)
                    right--;

                //如果三数之和<0表名左指针值太小,令其右移
                while((A[i]+A[left]+A[right])<0)
                    left++;

                //如果left>=right退出循环
                if(left>=right)
                    break;
            }
            if(left>=right)
                continue;
            while((A[i]+A[left]+A[right])==0)
            {
                //pair<pair<int,int>,int> x;
                //x.fist为最内层的pair,其包括x.first.first与x.first.second
                //x.second则为外层pair的second
                x.first.first = A[i];
                x.first.second = A[left];
                x.second = A[right];
                
                //set<pair<pair<int,int>,int>> flag;
                //如果x在此之前没有出现过那么flag.count(x)的值为0
                //否则为1
                if(flag.count(x)==0)
                {
                    //如果此前没有出现过这个三元组,则将其储存在flag中
                    flag.insert(x);

                    //将这个结果存入ans中
                    ans.push_back({A[i],A[left],A[right]});
                }

                //如果此前已经出现过则进行判断
                else if(flag.count(x)==1)
                {
                    while(A[left] == A[left+1])
                    {
                        left++;
                        if(left == len-1)
                            break;
                    }
                    while(A[right] == A[right-1])
                        right--;
                    if(left>=right)
                        break;
                    left++;
                    right--;
                }
                
                while((A[i]+A[left]+A[right])!=0)
                {
                    while((A[i]+A[left]+A[right])>0)
                        right--;
                    while((A[i]+A[left]+A[right])<0)
                        left++;
                    if(left>=right)
                        break;
                }
            if(left>=right)
                break;
            }
        }

        return ans;
    }
};

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值