leetcode题:15. 三数之和(中等)

本文介绍了一种解决三数之和问题的有效算法。通过先排序后使用双指针技术,寻找数组中是否存在三个数相加等于零的情况,并确保结果中没有重复的三元组。该方法适用于LeetCode上的经典问题。

一、题目描述:15. 三数之和(中等)

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、解题思路

1、先对数组进行升序排序。

2、从左到又开始遍历i,由于三个元素a+b+c=0;则,-a = (b+c);也就是说,对每个下标为i的数字,只要找到i右边所有和为-a的组合就可以,由于数组是升序排序的,所有使用双指针(下标)解法,定义双指针left = i+1,right=len-1;(注意:1)遍历的时候如果nums[i]==nims[i-]则continue,因为同一个数字,找到的组合是相同的,没必要再找了。2)当nums[i] 大于0的时候也没必要找了,因为此时i右边的数字都是大于0的,所有i和i右边的数字的组合,a+b+c恒大于0。此时break跳出循环就可以)

3、当left<right的时候,如果nums[left] + nums[right] 小于-a的话则left++(为了保证不会有重复组合,同时如果nums[left-1] == nums[left]的话,继续left++,left的数字和前一个数字不一致为止)。

4、当left<right的时候,如果nums[left] + nums[right] 大于-a的话则right--(为了保证不会有重复组合,同时如果nums[right] == nums[right+1]的话,继续right--,right的数字和后一个数字不一致为止)

5、如果nums[left] + nums[right] == -a,说明找到了a+b+c =0 的组合,将组合保存,left++,right--。(同时为了去重,当nums[left] == nums[left-1]的时候,继续left++。nums[right] == nums[left+1]的时候,继续right--。因为如果当前数字已经找过了组合,后面数字相同的话找到的组合是一样的,再找的话就是重复的)

三、代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int len = nums.size();
        vector<vector<int>> saveArray;
        for(int i = 0 ;i < len-1;i++)
        {
            if(i >0 && nums[i]== nums[i-1])
                continue;
            if(nums[i] > 0)
                break;
            int left = i+1,right = len - 1;
            int tmp = -1 * nums[i];
            while(left < right)
            {
                int sum_t = nums[left] + nums[right];
                if(sum_t < tmp)
                {
                    left++;
                    while(left>0 && left< len&& nums[left-1] == nums[left])
                        left++;
                }
                else if(sum_t > tmp)
                {
                    right--;
                    while((right<len-1 && right>=0 && nums[right] == nums[right+1]))
                        right--;
                }
                else
                {
                    /*
                    cout<<"i="<<i<<endl;
                    cout<<"nums[i]="<<nums[i]<<endl;
                    cout<<"left="<<left<<endl;
                    cout<<"right="<<right<<endl;
                    cout<<"nums[left]="<<nums[left]<<endl;
                    cout<<"nums[right]="<<nums[right]<<endl;
                    */
                    vector<int> save;
                    save.push_back(nums[i]);
                    save.push_back(nums[left]);
                    save.push_back(nums[right]);

                    left++;
                    right--;
                    while(left>0 && left< right&& nums[left-1] == nums[left])
                        left++;
                    while((right<len-1 && right>left && nums[right] == nums[right+1]))
                        right--;
                    saveArray.push_back(save);

                }
            }
        }
        return saveArray;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值