1. 题目
来源:力扣(LeetCode)
给你一个由 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
你可以按 任意顺序 返回答案 。
2. 解题思路
- 四个数求和去与目标值判断比较
- 正常思路4重循环
- 排除重复求和问题,先进行排序,用srot()即可
- 避免暴力循环,采用两层外循环+双指针方式
由以上思考得到一般思路:
- 先对数组排序,升序排列。在得到的数组中,从左开始两层嵌套循环定义前两个数A和B;
- 从接下剩下的数中,定义一个遍历,前后指针去获取两个数C和D;
- 判断A+B+C+D的值,若比目标值大,尾指针前移,若比目标指针销,前指针后移,若相等,则保存A B C D 的值,两个指针均往里靠;
- 遍历过程中由于是前后指针,当相遇的时候退出;依次执行遍历之外的循环。
【注意:】排序之后,数组中存在重复数字,查找答案是可能存在相同的答案,只要保证A,B,C ,D四个数字在每次计算得到目标结果后,不与上次相同即可,但是ABCD四个数是可以相等的即A=B=C=D。
【优化:】在排序之后,数字从小到大,在一二层循环中可增加判断初始的一二个数和最尾段的和,若该和小于目标值,则该层循环结束,进入下一层循环,即增加第1或第2个数字的大小。更快接近目标值。
3. 参考代码
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
// 标准库排序方法
std::sort(nums.begin(), nums.end());
std::vector<std::vector<int>> res;
if (nums.size()<4)
return res;
// 三重循环
// 第一重代表第一个数
for (size_t i = 0; i < nums.size()-3; i++)
{
int num1;
if (i>0&&nums[i]==nums[i-1])
continue;
else
num1 = nums[i];
// 第一重代表第二个数
for (size_t j = i+1; j < nums.size()-2; j++)
{
int num2;
if (j > i+1 && nums[j]==nums[j-1])
continue;
else
num2 = nums[j];
// 第三重循环选择移动 第3个数或者第4个数
size_t k = j+1;
size_t w = nums.size()-1;
while (k<w)
{
int num3 = nums[k];
int num4 = nums[w];
int temp = num3 +num4;
if ((target -num1 - num2) > temp)
{
k = k+1;
continue;
}
else if ((target -num1 - num2) < temp)
{
w = w-1;
continue;
}
else
{
std::vector<int> re={num1 , num2 , num3 ,num4};
res.push_back(re);
w--;
while (k<w && (nums[++k] == nums[k-1])){}
continue;
}
}
}
}
return res;
}
};