LeetCode 18 四数之和 HERODING的LeetCode之路

该博客介绍了如何使用排序和双指针策略解决寻找数组中四个元素之和等于目标值的问题。通过排序数组,然后用两个外层循环固定较小的两个元素,内部使用双指针调整另外两个元素,避免了暴力求解的复杂度,提高了效率。文章还提供了具体的C++代码实现,并解释了如何处理重复解和优化时间复杂度。
摘要由CSDN通过智能技术生成

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

注意:

答案中不可以包含重复的四元组。

示例:

给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

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

解题思路:
初识此题也是百思不得其解,想要继续使用递归回溯的方法,看到评论才发现超时了。。。暴力解法过于暴力不够灵活,于是发现了一种排序+双指针的方法,也就是使用a,b,c,d四个数,for循环a和b,然后在循环中,不断改变c,d的位置,c初始位置是b的后一位,d初始位置是最后一位,中间的去重也很精妙,是通过判断左右两边是否有重复数字,然后跳过的方法,这样避免了使用相同的结果,官方的解题思路我也贴出来:

四数之和与前面三数之和的思路几乎是一样的,嗝。(刚好前些天才写了三数之和的题解)
如果前面的三数之和会做了的话,这里其实就是在前面的基础上多添加一个遍历的指针而已。
会做三数之和的可以不用看下面的了。。

使用四个指针(a<b<c<d)。固定最小的a和b在左边,c=b+1,d=_size-1 移动两个指针包夹求解。
保存使得nums[a]+nums[b]+nums[c]+nums[d]==target的解。偏大时d左移,偏小时c右移。c和d相
遇时,表示以当前的a和b为最小值的解已经全部求得。b++,进入下一轮循环b循环,当b循环结束后。
a++,进入下一轮a循环。 即(a在最外层循环,里面嵌套b循环,再嵌套双指针c,d包夹求解)。
准备工作:
因为要使用双指针的方法,排序是必须要做der~。 时间复杂度O(NlogN).
解决重复解:
上面的解法存在重复解的原因是因为移动指针时可能出现重复数字的情况。所以我们要确保移动指针后,
对应的数字要发生改变才行哦。
时间复杂度:
a遍历O(N)里嵌套b遍历O(N)再嵌套c,d双指针O(N)–> O(N^3)。 总比暴力法O(N^4)好些吧。。

c++ 实现代码

class Solution{
	public: 
	vector<vector<int>> fourSum(vector<int>& nums, int target) {
        // 排序
        sort(nums.begin(),nums.end());
        // 结果的集合
        vector<vector<int> > res;
        if(nums.size()<4){
           return res; 
        }
        int a,b,c,d,_size = nums.size();
        for(a = 0; a <= _size - 4; a ++){// a 是外包围
        	if(a > 0 && nums[a] == nums[a - 1]) continue;      //确保nums[a] 改变了
        	for(b = a + 1; b <= _size - 3; b++){
        		if(b > a + 1 && nums[b] == nums[b - 1])continue;   //确保nums[b] 改变了
        		c= b + 1,d= _size - 1;
        		while(c < d){
        			if(nums[a] + nums[b] + nums[c] + nums[d] < target)
        			    c ++;//不够c右移
        			else if(nums[a] + nums[b] + nums[c] + nums[d] > target)
        			    d --;//多了d左移
        			else{
        				res.push_back({nums[a],nums[b],nums[c],nums[d]});
        				while(c < d && nums[c + 1] == nums[c])      //确保nums[c] 改变了
        				    c++;
        				while(c < d && nums[d - 1] == nums[d])      //确保nums[d] 改变了
        				    d--;
        				c++;
        				d--;
					}
				}
			}
		}
		return res;
    }
};

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HERODING77

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

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

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

打赏作者

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

抵扣说明:

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

余额充值