18.四数之和
18.四数之和
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n a、b、c 和 d 互不相同 nums[a] + nums[b] + nums[c] + nums[d] == target 你可以按 任意顺序 返回答案 。
思路
基本思想
相比于
15题
,本题就是多了一个数,并且数的和不再是0而是target
,但是基本的思路还是一样的,只需要将三数之和进行简单的改造,如果题解看不懂,需要先看15题的题解
将问题分解,四数之和分成一个数与三个数的和,这样问题就变成了三数之和的问题
只是三数之和的目标不再是0,而是target-nums[i]
,这个nums[i]
就是第四个数,这四个数相加刚好是target
为了实现一个数与三个数的和,首先需要从nums
中取出一个数,然后从余下的元素中使用三数之和的方法找出符合条件的数组成四元组
从nums中取出元素的操作,需要注意去重,也就是说不能从相同的元素开始搜索
整道题的逻辑就是建立在 15题 的基础上,只是编写代码时需要注意细心
核心的地方有两点:
去重的时候有三个地方都需要去重
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
//第一次去重 if(nums[i]>target&&nums[i]>0) break; if(i>0&&nums[i]==nums[i-1]) continue; //第二次去重,仿照第一次去重的经验 if(nums[j] + nums[i] > target && nums[j] + nums[i] >= 0) break; //防止从重复的元素出发搜索剩下的元素 if(j>i+1&&nums[j]==nums[j-1]) continue; //第三次去重 while(left<right&&nums[right]==nums[right-1]) right--; while(left<right&&nums[left]==nums[left+1]) left++;
四数之和可能超过int的范围,需要类型转换
1
long sum=(long)nums[i]+nums[j]+nums[left]+nums[right];
剩下的都仿照15题即可
执行流程
- 对元素进行排序
- 从第一个元素出发,搜索剩下的三个元素,出发时需要去重,第一次去重
- 从第二个元素出发,搜索剩下的两个元素,出发时需要去重,第二次去重
- 从余下的元素中搜索剩下的两个元素组成四元素,注意形成四元组之后,需要第三次去重
- 返回最终的结果
代码
根据以上分析,得出以下代码:
|
|
总结
问题分割成一个数与另外三个数的和,三个数的和可以应用 15题 的解法,只是在15题的解法上需要再加一层for循环,所以最终需要两层for循环,并且两层for循环起始点不可以相同,防止出现相同的四元组