454.四数相加II
题目链接/文章讲解/视频讲解:代码随想录
这道题给我最大的启示是,要把四个数,两两拆分;然后分别建立哈希表。
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
// 重要的思路:两两拆分
unordered_map<int, int> umap;
for (int a : nums1) {
for (int b : nums2) {
++ umap[a + b];
}
}
int count = 0;
for (int c : nums3) {
for (int d : nums4) {
if (umap.find( 0 - (c + d)) != umap.end()) {
count += umap[ 0 - (c + d)];
}
}
}
return count;
}
};
383.赎金信
题目链接/文章讲解: 代码随想录
这道题对我来说最难的提示是理解题意,并把整个过程抽象成为代码。
如果只是看代码,其实可以说是前面的练习题的延伸。把前面好多思路融合到一起了。
眼高手低,代码还是要练才行。
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int record[26] = {};
// 杂志的字符数量比信的字符数量多
if (ransomNote.size() > magazine.size()) {
return false;
}
// 统计字符数量
for (int i = 0; i < magazine.size(); ++i) {
record[magazine[i]-'a']++;
}
// 去核对数量,如果不够多,则返回false
for (int i = 0; i < ransomNote.size(); ++i) {
record[ransomNote[i]-'a']--;
if(record[ransomNote[i]-'a'] < 0) {
return false;
}
}
return true;
}
};
15.三数之和
题目链接/文章讲解/视频讲解: 代码随想录
寄了,这道题属于,一上来题目看不懂,看答案解析也看不懂的类型。
对答案和注释一行一行的研读,才能勉强懂一点,但还是太抽象了。找时间要多看多想。
三指针的思路:i指针用于遍历,left指针用于减小总和,right指针用于增加总和。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); i++) {
// 排序后,如果最小的都大于0,则正数相加不会为0
if (nums[i] > 0) {
return result;
}
// 对 第一个加数 去重
if (i > 0 && nums[i] == nums[i-1]) {
continue;
}
// 三个指针:i、left、right
// i决定了遍历的起点,left和right用于调整总和的大小
// 真题实际上就是在根据结果来调整区间长度
int left = i + 1;
int right = nums.size() - 1;
while ( left < right ) {
if (nums[i] + nums[left] + nums[right] > 0) {
right--;
}
else if (nums[i] + nums[left] + nums[right] < 0) {
left++;
}
else{
// 这里是 对左指针、有指针 去重
result.push_back(vector<int>{nums[i], nums[left], nums[right]});
while (left < right && nums[right] == nums[right-1]){
right--;
}
while (left < right && nums[left] == nums[left + 1]){
left++;
}
right--;
left++;
}
}
}
return result;
}
};
18.四数之和
题目链接/文章讲解/视频讲解: 代码随想录
这道题是上一道题的进阶版。
也是用三个指针来操作。
这道题里的剪枝,即为上一道题里所说的去重。
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>>result;
sort(nums.begin(), nums.end());
for (int k = 0; k < nums.size(); k++ ) {
// 剪枝处理
if (nums[k] > target && nums[k] >= 0) {
break;
}
// 对 nums[k] 去重
if (k > 0 && nums[k] == nums[k - 1]) {
continue;
}
//
for (int i = k + 1; i < nums.size(); i++) {
// 二级剪枝处理
if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) {
break;
}
// 对 nums[i] 去重
if (i > k + 1 && nums[i] == nums[i - 1]) {
continue;
}
// 双指针法,缩小窗口
int left = i + 1;
int right = nums.size() - 1;
while (right > left) {
if ((long) nums[k] + nums[i] + nums[left] + nums[right] > target) {
right--;
}
else if ((long) nums[k] + nums[i] + nums[left] + nums[right] < target) {
left++;
}
else {
result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
// 对 left和right 去重
while (right > left && nums[right] == nums[right - 1]) {
right--;
}
while (right > left && nums[left] == nums[left + 1]) {
left++;
}
right--;
left++;
}
}
}
}
return result;
// vector<vector<int>> result;
// sort(nums.begin(), nums.end());
// for (int k = 0; k < nums.size(); k++) {
// // 剪枝处理
// if (nums[k] > target && nums[k] >= 0) {
// break; // 这里使用break,统一通过最后的return返回
// }
// // 对nums[k]去重
// if (k > 0 && nums[k] == nums[k - 1]) {
// continue;
// }
// for (int i = k + 1; i < nums.size(); i++) {
// // 2级剪枝处理
// if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) {
// break;
// }
// // 对nums[i]去重
// if (i > k + 1 && nums[i] == nums[i - 1]) {
// continue;
// }
// int left = i + 1;
// int right = nums.size() - 1;
// while (right > left) {
// // nums[k] + nums[i] + nums[left] + nums[right] > target 会溢出
// if ((long) nums[k] + nums[i] + nums[left] + nums[right] > target) {
// right--;
// // nums[k] + nums[i] + nums[left] + nums[right] < target 会溢出
// } else if ((long) nums[k] + nums[i] + nums[left] + nums[right] < target) {
// left++;
// } else {
// result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
// // 对nums[left]和nums[right]去重
// while (right > left && nums[right] == nums[right - 1]) right--;
// while (right > left && nums[left] == nums[left + 1]) left++;
// // 找到答案时,双指针同时收缩
// right--;
// left++;
// }
// }
// }
// }
return result;
}
};