15. 三数之和(C++)---(排序+双指针)解题

题目详情
 

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

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

 

示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]


——题目难度:中等


 


 
这道题的暴力解法比较好想,就是使用三重循环枚举所有可能的三元组,但假设最坏的情况下,数组中元素全是0则太费时间(因为很多组都是重复的,最后如果要解题还得去重)。

这里借用一下力扣题解里的,我觉得总结的非常好:

「不重复」的本质是什么?我们保持三重循环的大框架不变,只需要保证:

  • 第二重循环枚举到的元素不小于当前第一重循环枚举到的元素;
  • 第三重循环枚举到的元素不小于当前第二重循环枚举到的元素。

其实也就是:假设有这样一个三元组(a,b,c),其中a≤b≤c,当暴力三重循环解出来的会有(b,a,c)、(c,b,a)、(a,c,b)等等。
所以我们优化的时候可以使得ans里不存在重复的三元组,要做到只需将原数组排好序,这样再三重循环的话就不会出现除了(a,b,c)的情况,因为a≤b≤c这是必须满足的。

然后可以发现第二层和第三层的for循环(也就是枚举second和third的) 其实是可以改进的。a+b+c=0,当a不变,b往后遍历也就是不断变大,发现要满足a+b+c=0的话,其实c是不断在减小的,所以我们可以从小到大枚举b,同时从大到小枚举c。当发现a+b+c<0的时候,可以令b变大以满足等式;当发现a+b+c>0的时候,可以令c变小以满足等式。

同时要注意 b<=c,也要注意第一层for循环枚举a的时候,需要保证a每次都不一样,b和c类似a的情况。

 



-解题代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
    	vector<vector<int>> ans;
		int n = nums.size();
		if (n < 3) return ans;
		
		sort(nums.begin(), nums.end());
		for(int first = 0; first < n-2; first++)
		{
			if(first > 0 && nums[first] == nums[first-1]) 
				continue;
			
			int target = -nums[first];
			int second = first + 1;
			int third = n - 1;
			while (second < third) {
				int sum = nums[second] + nums[third];
				if (sum == target) {
					ans.push_back({nums[first], nums[second], nums[third]});
				
					while(second < third && nums[second] == nums[second+1]) {
						second++;
					}
					second++;
					
					while(second < third && nums[third] == nums[third-1]) {
						third--;
					}
					third--;
				} else if (sum > target) {
					third--;
				} else {
					second++;
				}
			}
		}
			
		return ans;	
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重剑DS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值