一、454.四数相加II
本题只需要写出满足要求的组数,故较为简单:

若改为要求返回 i, j, k, l 的值,则代码为:
vector<vector<int>> fourSumUniqueValues(vector<int>& nums1, vector<int>& nums2,
vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, vector<pair<int, int>>> sumMap;
set<vector<int>> uniqueTuples;
// 构建 nums1 与 nums2 的所有和值及其索引
for (int i = 0; i < nums1.size(); ++i) {
for (int j = 0; j < nums2.size(); ++j) {
int sum = nums1[i] + nums2[j];
sumMap[sum].emplace_back(i, j);
}
}
// 遍历 nums3 和 nums4,看是否存在可配对的 target
for (int k = 0; k < nums3.size(); ++k) {
for (int l = 0; l < nums4.size(); ++l) {
int target = -(nums3[k] + nums4[l]);
if (sumMap.count(target)) {
for (auto& [i, j] : sumMap[target]) {
vector<int> quad = {nums1[i], nums2[j], nums3[k], nums4[l]};
sort(quad.begin(), quad.end()); // 排序后去重
uniqueTuples.insert(quad);
}
}
}
}
// 将结果转为 vector<vector<int>>
return vector<vector<int>>(uniqueTuples.begin(), uniqueTuples.end());
}
此处需要记录i, j, k, l,故需要创建一个map:
![]()
其中,sum作为key键,[i, j]作为value来储存结果。
二、383. 赎金信

注意点:比较数组和字符串在迭代器写法中的差异。
三、15. 三数之和
本题难点在于去重。
开始思路想过创建一个set来为数组中的元素去重,但是之后思考并不满足题意:
即存在(1,1,-2)这样的三元组满足题意,但是如用set去重则会将这个答案也删去,故不行。
结果代码如下:

其中,值得注意是剪枝操作:
1处为:排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果。
2处 i>1的限制条件,一为防止i-1越界访问,二为了防止漏掉-1,-1,2 这种情况。
3处 while循环中left < right的限制条件:

起初想的是外部的大while循环会限制 left < right,但是内部会优先越界访问造成无限循环,故需要在内部添加限制条件。
四、18. 四数之和
思路同上,主要是几个注意点:

这题不能提前返回res,可能后续会有符合结果的组合,故使用break在代码结尾统一返回。
long定义sum来防止int上下限溢出,sum需要定义在while( left < right)内部,来保证sum每次循环重新计算。
以及break的一重剪枝需要和三数之和做区分:


被折叠的 条评论
为什么被折叠?



