目录
15. 三数之和 18. 四数之和 不理解
454.四数相加II
题目链接:454. 四数相加 II
给你四个整数数组
nums1
、nums2
、nums3
和nums4
,数组长度都是n
,请你计算有多少个元组(i, j, k, l)
能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
示例 1:
输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2] 输出:2 解释: 两个元组如下: 1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0 2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0示例 2:
输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0] 输出:1
unordered_map:
相对于后面的三数之和 四数之和 简单的地方在于 1. 四个独立的数组,不用考虑元素重复的问题; 2. 只需返回满是条件的组合个数,不用返回具体的下标数组
-
力扣代码:
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
int count = 0;
// 遍历 nums1 nums2 数组,计算两数之和,并在 unordered_map value 中存储出现的次数
std::unordered_map<int, int> umap;
for (int i = 0; i < nums1.size(); i++) {
for (int j = 0; j < nums2.size(); j++) {
auto pos = umap.find(nums1[i] + nums2[j]); // 先判断在之前是否出现
count = pos == umap.end() ? 1 : ++pos->second;
umap.emplace (nums1[i] + nums2[j], count);
}
}
count = 0; // 清零
// 遍历 nums3 nums4 数组,计算两数之和,并在上面的 unordered_map 中找到和为0的匹配值,记录出现的次数count
for (int i = 0; i < nums3.size(); i++) {
for (int j = 0; j < nums4.size(); j++) {
auto pos = umap.find( 0 - (nums3[i] + nums4[j]));
if (pos != umap.end()) count+= pos->second;
}
}
return count;
}
};
15. 三数之和
题目链接:15. 三数之和
给你一个整数数组
nums
,判断是否存在三元组[nums[i], nums[j], nums[k]]
满足i != j
、i != k
且j != k
,同时还满足nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为
0
且不重复的三元组。注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]] 解释: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意,输出的顺序和三元组的顺序并不重要。示例 2:
输入:nums = [0,1,1] 输出:[] 解释:唯一可能的三元组和不为 0 。示例 3:
输入:nums = [0,0,0] 输出:[[0,0,0]] 解释:唯一可能的三元组和为 0 。
双指针法:
-
力扣代码:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
// 双指针法, 没有内化它的实现逻辑
vector<vector<int>> resultVector;
int left = 0; // 数组索引
int right = nums.size() - 1;
sort(nums.begin(), nums.end());
// 遍历 nums
for (int i = 0; i < nums.size(); i++) {
if (nums[i] > 0) return resultVector; // 判断第一个是否小于0
// 对 i 去重
if (i > 0 && nums[i] == nums[i-1]) continue;
left = i + 1;
right = nums.size() - 1;
// 移动 left right 两个指针
while (left < right) {
if ( (nums[i] + nums[left] + nums[right]) > 0 ) right--;
else if ( (nums[i] + nums[left] + nums[right]) < 0 ) left++;
else {
resultVector.push_back({nums[i], nums[left], nums[right]});
// 去重 left right
while (left < right && nums[left] == nums[left+1]) left++;
while (left < right && nums[right] == nums[right-1]) right--;
left++;
right--;
}
}
}
return resultVector;
}
};
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
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]示例 2:
输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]]
双指针法:
-
力扣代码: