- 454.四数相加
- 思路:
- 类似于两数之和,不过是先两两数组间求出和,然后使用map来记录各个sum的频次;至于为什么不用set或者普通数组的原因也一致,因为要记录元素值和频次两个变量
- 不同位置元素不论数值是否相等,符合要求就要加频次;第二个双层循环中对count并不是简单的自加一
- 优化:(如下)
- 第一个双层循环内部逻辑写复杂了
- 双层循环可以用foreach
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, int> abNum;
int count = 0;
for (int i = 0; i < nums1.size(); i++) {
for (int j = 0; j < nums2.size(); j++){
int curSum = nums1[i] + nums2[j];
if (abNum.find(curSum) != abNum.end()) {
abNum[curSum]++;
}else {
abNum.insert(make_pair(curSum, 1));
}
}
}
for (int i = 0; i < nums3.size(); i++) {
for (int j = 0; j < nums4.size(); j++) {
int curSum = (0 - (nums3[i] + nums4[j]));
if (abNum.find(curSum) != abNum.end()) {
count += abNum[curSum];
}
}
}
return count;
}
};
class Solution {
public:
int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
unordered_map<int, int> umap;
for (int a : A) {
for (int b : B) {
umap[a + b]++;
}
}
int count = 0;
for (int c : C) {
for (int d : D) {
if (umap.find(0 - (c + d)) != umap.end()) {
count += umap[0 - (c + d)];
}
}
}
return count;
}
};
- 383.赎金信
- 由于未看到题干中string只由小写字母组成,这里使用了map而不是数组,空间消耗更大些,但更适用
- 对foreach的理解加深了
- 注意看代码注释,第三个for循环处
- 在C++中,对于一个未赋初值的 std::map,使用 map[key]++ 是合法的。这是因为,如果 key 在 map 中不存在,map[key] 会自动插入一个默认构造的值(对于 int 类型,默认是0),然后将其递增。如果 key 已经存在,那么它的值将被递增。
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
unordered_map<char, int> _map;
for (int i = 0; i < ransomNote.size(); i++) {
_map[ransomNote[i]]++;
}
for (char x : magazine) {
_map[x]--;
}
for (auto x : _map) {
if (x.second > 0) return false;
}
return true;
}
};
- 15.三数之和
- 二维vector赋值({ , , ,})
- 去重操作
- while内部双层判断的问题:若内层不加(left<right)这个条件可能会出现数组越界,这是由于本次循环的循环体可能在当前循环进入时合法的情况下,在本次循环体内出现了导致非法操作;eg:{0,0,0,0}
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); i++) {
if (nums[i] > 0) return res;
if (i > 0 && nums[i] == nums[i - 1]) continue;
int left = i + 1;
int right = nums.size() - 1;
while (left < right) {
if (nums[i] + nums[left] + nums[right] < 0) {
left++;
}else if (nums[i] + nums[left] + nums[right] > 0) {
right--;
}else {
res.push_back({nums[i],nums[left],nums[right]});
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) right--;
left++;
right--;
}
}
}
return res;
}
};
- 18.四数之和
- 主要在于剪枝与去重
- 最内层的while逻辑还是会出错
- 四数相加判断时需强转为long否则会溢出
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
sort(nums.begin(),nums.end());
for (int i = 0; i < nums.size(); i++) {
if (nums[i] > target && nums[i] > 0) break;
if (i > 0 && nums[i] == nums[i - 1]) continue;
for (int j = i + 1; j < nums.size(); j++) {
if (nums[i] + nums[j] > target && nums[i] + nums[j] > 0) break;
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
int left = j + 1;
int right = nums.size() - 1;
while (left < right) {
if ((long)nums[i] + nums[j] + nums[left] + nums[right] < target) left++;
else if ((long)nums[i] + nums[j] + nums[left] + nums[right] > target) right--;
else {
res.push_back({nums[i],nums[j],nums[left],nums[right]});
while (left < right && nums[right] == nums[right - 1]) right--;
while (left < right && nums[left] == nums[left + 1]) left++;
left++;
right--;
}
}
}
}
return res;
}
};