letcode 分类练习 x个数之和问题 15. 三数之和 18. 四数之和 454. 四数相加 II 383. 赎金信
- 三数之和
- 四数之和
- 454. 四数相加 II
- 383. 赎金信
三数之和
三数之和,双指针模版代码,注意去重逻辑,还有只需要去重第一和第二重循环,第三重循环就不用去重了,这是因为只要找到了一个三元组,第二重循环就会往下走,那么下一个三元组是不可能有重复的三元组的。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> result;
for(int i = 0;i<nums.size();i++){
if(i > 0 && nums[i] == nums[i-1])continue;
int z = nums.size() - 1;
for(int j = i + 1;j<nums.size();j++){
if(j > i + 1 && nums[j] == nums[j-1])continue;
while(j < z && nums[z] + nums[i] + nums[j] > 0){z--;}
if(j == z) break;
if(nums[z] + nums[i] + nums[j] == 0)
result.push_back(vector<int>({nums[z],nums[i],nums[j]}));
}
}
return result;
}
};
四数之和
还是一样的套路,最后一层不去重,这里还得注意四个数求和不要溢出,做法是
long sum = (long) nums[i] + nums[j] + nums[x] + nums[y]
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
int n = nums.size();
vector<vector<int>> results;
sort(nums.begin(), nums.end());
for(int i = 0;i<n;i++){
if(i>0 && nums[i] == nums[i-1]) continue;
for(int j = i+1;j<n;j++){
if(j>i+1 && nums[j] == nums[j-1]) continue;
int y = n-1;
for(int x = j + 1;x<n;x++){
if(x > j + 1 && nums[x] == nums[x-1]) continue;
long sum = (long)nums[i] + nums[j] + nums[x] + nums[y];
while(y > x && sum > target){
y--;
sum = (long)nums[i] + nums[j] + nums[x] + nums[y];
}
if(y == x) break;
if(sum == target){
results.push_back({nums[i] , nums[j] , nums[x] , nums[y]});
}
}
}
}
return results;
}
};
454. 四数相加 II
这个题注意是求元祖数量(这个是允许重复的),将4数之和转成两数之和(A+B, C + D),之后用hash表就行了
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
int l1 = nums1.size(); int l2 = nums2.size(); int l3 = nums3.size(); int l4 = nums4.size();
unordered_map<int, int> map;
for(int i = 0;i<l1;i++){
for(int j = 0;j< l2;j++){
int sum_12 = nums1[i] + nums2[j];
if(map.count(sum_12))map[sum_12]++;
else map[sum_12] = 1;
}
}
int count = 0;
for(int x = 0; x< l3;x++){
for(int y = 0;y< l4;y++){
int target = 0 - nums3[x] - nums4[y];
if(map.count(target)) count+= map[target];
}
}
return count;
}
};
383. 赎金信
用hash表即可解决,字母hash表(size = 26)
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
vector<int> num(26, 0);
for(auto m : magazine){
num[m - 'a']++;
}
for(auto r : ransomNote){
if(num[r - 'a'] <= 0) return false;
else num[r - 'a']--;
}
return true;
}
};