- 四数相加 II
- 赎金信
- 三数之和
- 四数之和
454. 四数相加 II
第一想法
- 这是一个数据无相关性的四个数组,只要每个数组都顺序遍历,就能找到符合条件的答案,不用考虑重复性。所以,只要考虑如何减少时间复杂度就好。如果是暴搜,就是四重循环,不太行。
- 那么考虑一下先算前两个数组,再算后两个数组,看是否有为相反数的存在。本题值需要返回个数,而不需要返回下标,所以只要记下来每个结果出现几次,然后找到相符的就可以
代码
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, int> map;
int count = 0;
for (int i = 0; i < nums1.size(); i ++){
for (int j = 0; j < nums2.size(); j ++){
map[nums1[i] + nums2[j]] ++;
}
}
for (int i = 0; i < nums3.size(); i ++){
for (int j = 0; j < nums4.size(); j ++){
if (map.find(-nums3[i] - nums4[j]) != map.end())
count += map[-nums3[i] - nums4[j]];
}
}
return count;
}
};
383. 赎金信
第一想法
第一个string中每个字母出现的次数,一定小于第二个string中每个字幕出现的次数。所以统计一下第二个string每个字母出现多少次,然后遍历第一个string,看最后的结果是否有没出现过的字母或者出现次数不够即可。统计次数和快速查找字幕出现次数适合用unordered_map
。
代码
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
if (ransomNote.size() > magazine.size()) return false;
unordered_map<char, int> map;
for (auto a: magazine) map[a] ++;
for (auto b: ransomNote){
if (map.find(b) == map.end() || map[b] == 0)
return false;
map[b] --;
}
return true;
}
};
15. 三数之和
第一想法
题目返回的是不重复出现的和为0的三个数数值,所以不管怎么搜索,其实最重要的是去重。
- 第一种想法是直接对数组去重,然后找相加为0的数值。
- 第二种想法是,三个指针
i, j, k
遍历去寻找,如果找到nums[i] == nums[i-1]
则要去重,这样其实是在- 1 -1 2遍历到第二个-1时进行去重,第一个遍历的时候是可以保留结果的。
代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
// -4 -1 -1 0 1 2
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); i ++){
if (i && nums[i] == nums[i - 1]) continue;
for (int j = i + 1, k = nums.size() - 1; j < k; j ++){
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
while (j < k - 1 && nums[i] + nums[j] + nums[k] > 0)
k --;
if (nums[i] + nums[j] + nums[k] == 0)
res.push_back({nums[i], nums[j], nums[k]});
}
}
return res;
}
};
18. 四数之和
第一想法
和三数之和一样,只不过要多加一层循环。
代码
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
vector<vector<int>> res;
for (int i = 0; i < nums.size(); i ++){
if (i && nums[i] == nums[i - 1]) continue;
for (int j = i + 1; j < nums.size(); j ++){
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
for (int k = j + 1, z = nums.size() - 1; k < z; k++){
if (k > j + 1 && nums[k] == nums[k - 1])
continue;
while (k < z - 1 && (long long)nums[i] + nums[j] + nums[k] + nums[z] > target) z--;
if ((long long)nums[i] + nums[j] + nums[k] + nums[z] == target)
res.push_back({nums[i], nums[j], nums[k], nums[z]});
}
}
}
return res;
}
};