454. 四数相加
一开始思路是两两相加,但考虑到压入哈希表时会导致相同加和的元素只有一个取值无法统计,所以没有继续。实际上使用map的key-value键值对可以既储存元素又储存相同元素的个数。
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
int res = 0;
std:: unordered_map <int,int> map;
for (int a : nums1){
for (int b : nums2){
map[a + b]++;
}
}
for (int c : nums3){
for (int d : nums4){
if (map.find(-(c + d)) != map.end())
res += map[-(c + d)];
}
}
return res;
}
};
383. 赎金信
和字母异位词思路相同。注意record在初始化时要全部赋0值,否则后续if判断无法全部生效。
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int record[26] = {0};
for (char letter : magazine)
record[letter - 'a']++;
for (char letter : ransomNote){
record[letter - 'a']--;
if (record[letter - 'a'] < 0)
return false;
}
return true;
}
};
15. 三数之和
力扣官方题解里对一步步推导到双指针的思路过程描述得比较详细。首先对数组进行排序,排序后三层循环中后两层就可以使用首尾双指针化为一层。
本题还需要注意去重时的判断,不是if (nums[i] == nums[i+1])
而是if (nums[i-1] == nums[i])
,这样才能保证i和i+1同时成为三元组的元素的情况被考虑在内。此外实际上并不需要对第三个元组值手动去重,因为当第二个值去重后移之后,第三个值一定不满足三元组。
18. 四数之和
思路:同上,注意四数相加时可能会溢出,要转化为long型。注意剪枝处理。
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
int n = nums.size();
int i = 0;
for (; i < n; i++){
if(nums[i] > target && nums[i] >= 0)
break;
if (i > 0 && nums[i] == nums[i - 1])
continue;
for (int j = i + 1; j < n - 2; j++){
if (nums[i] + nums[j] > target && nums[i] + nums[j] >= 0)
continue;
if (j > i + 1 && nums[j] == nums[j - 1])
continue;
int left = j + 1;
int right = n - 1;
while (left < right){
if ((long)nums[i] + nums[j] + nums[left] + nums[right] > target)
right--;
else if ((long)nums[i] + nums[j] + nums[left] + nums[right] < target)
left++;
else{
result.push_back(vector<int>({nums[i], nums[j], nums[left], nums[right]}));
while(left < right && nums[left + 1] == nums[left])
left++;
right--;
left++;
}
}
}
}
return result;
}
};
总结
主要是熟悉题目。