力扣:三数之和---双指针解法---C++实现

题目链接 

        https://leetcode-cn.com/problems/3sum/

题目描述

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

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

示例:

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

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

解题思路

  1. 最容易想到的思路就是暴力解法,写个三重循环,把所有的情况都列举一般,但是这种解法一般都会超时,而且题目中还说了不能有重复的三元组,就比如输入的是-1,0,1,-1,0,1。这种在暴力的时候就会出现重复,所以还要想办法去重,所以这种解法一般不可取。
  2. 题目中提到是是不重复,那我们是不是可以首先进行排序,然后在筛选的时候三个数a,b,c的时候,保证a<=b<=c。这样是不是就少了一些重复的可能性,比如(a,b,c),(b,a,c),(c,b,a)这些就会被筛选掉了
  3. 当然满足a<=b<=c并不能把所以重复的情况去掉。比如-1,-1,-1,0,0,0,0,1,1,1(排序后)。这样根据上面的条件就无法解决了,下面说一个解决的办法
  4. 比如我们在选其中a的时候,如果a选-1了,那接下来在遍历的时候,a就不能在选-1.有没有啥好办法呢!办法就是:我们在进行遍历的时候,如果选a的这个数不是数组的第一个元素,那么判断一个这个数和这个数前面的数是否相等,如果相等,直接continue即可,因为a已经选过了。
  5. 既然三重循环求解会超时,那么我们可以先排序,再进行二重循环。
  6. 外层循环就是枚举第一个数a,在这个外层循环的里面首先要进行判断a是否重复使用过了(使用上面4的方法),再定义一个变量,用来扫描数组c。
  7. 然后就开始第二层循环,这个循环是枚举第二个数b,b从a后面的一个数开始枚举(从左到右扫描),同时也要判断b是否重复的问题,解决办法和a一样,在这二层循环里面,再用一个while循环,从右到左扫描c
  8. 虽然是二层循环里面套while循环,但是他并不是三重循环的时间复杂度。因为假如我们在固定a的情况下,找到了一对b和c满足了情况跟,接再来在枚举b和c的时候,实在上一个找到的情况下进行继续扫描的,如图所示:

代码

class Solution 
{
public:
    vector<vector<int>> threeSum(vector<int>& nums)
    {
        int len=nums.size();
        sort(nums.begin(),nums.end());
        vector<vector<int> > ans;
        //开始枚举 a 
        for(int first=0;first<len;first++)
        {
        	//需要和上一次枚举的数不相同 
            if(first>0&&nums[first]==nums[first-1])
                continue;
            int Target=-nums[first];
            // c 指向数组的最右端 
            int third=len-1;
            //开始枚举b 
            for(int second=first+1;second<len;second++)
            {
            	//需要和上一次枚举的数不相同 
                if(second>first+1&&nums[second]==nums[second-1])
                    continue;
                //需要保证b在c的左侧 
                while(second<third&&nums[second]+nums[third]>Target)
                    third--;
                //如果指针重合,随着b的增长,就不会有满足a+b+c=0了 
                if(second==third)
                    break;
                if(nums[second]+nums[third]==Target)
                    ans.push_back({nums[first],nums[second],nums[third]});
            }
        }
        return ans;
    }
};
扫描二维码关注公众号,回复: 11300760 查看本文章

猜你喜欢

转载自blog.csdn.net/weixin_44820625/article/details/106722826
今日推荐