LeetCode454. 四数相加 II
文章链接:代码随想录
题目链接:454. 四数相加 II
思路: 需要ket和value,用unordered_map遍历一下即可,由于分四个数组,故不用考虑重复的问题;和两数之和的问题很像;另外注意以下map的用法,和数组类似。
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, int> record;
int count = 0;
for (int a : nums1){
for (int b : nums2){
record[a + b]++;
}
}
for (int c : nums3){
for (int d : nums4){
if (record.find(0 - c - d) != record.end()){
count += record[0 - c - d];
}
}
}
return count;
}
};
LeetCode383. 赎金信
思路: key有限,用数组记录,最后出现负数即false,和 LeetCode242.有效的字母异位词 很像。
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int record[26] = {0};
for (char i : magazine){
record[i - 'a']++;
}
for (char i : ransomNote){
record[i - 'a']--;
}
for (int i : record){
if (i < 0){
return false;
}
}
return true;
}
};
用map也可以做,但时间(要做哈希运算)和空间占用都变大。
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
unordered_map<int, int> record;
for (char i : magazine){
record[i - 'a']++;
}
for (char i : ransomNote){
record[i - 'a']--;
if (record[i - 'a'] < 0){
return false;
}
}
return true;
}
};
LeetCode15. 三数之和
思路:用哈希表的方法暂时没做,采用双指针。
- 注意用双指针之前先排序
- 注意第一步去重时用continue,用 i++ 只能去一遍重。
- 注意先收缩和后收缩去重方法的不同
- 暂时没写剪枝,后续方法掌握熟练后有时间补全。
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++){
if (i > 0 && nums[i] == nums[i - 1]){
continue;
}
int l = i + 1, r = nums.size() - 1;
while (l < r){
if (nums[i] + nums[l] + nums[r] == 0){
result.push_back(vector<int> {nums[i], nums[l], nums[r]});
while (l < r && nums[l] == nums[l + 1]) l++;
while (l < r && nums[r] == nums[r - 1]) r--;
l++;
r--;
}
else if (nums[i] + nums[l] + nums[r] < 0){
l++;
}
else {
r--;
}
}
}
return result;
}
};
- 排序
sort (nums.begin(), nums.end());
- 第一步去重用continue
if (i > 0 && nums[i] == nums[i - 1]){
continue;
}
- 先去重后收缩:
while (l < r && nums[l] == nums[l + 1]) l++;
while (l < r && nums[r] == nums[r - 1]) r--;
l++;
r--;
先收缩后去重:
l++;
r--;
while (l < r && nums[l] == nums[l - 1]) l++;
while (l < r && nums[r] == nums[r + 1]) r--;
可以这样理解,将排序后的数组看成一级级的台阶,先去重是将指针移到了台阶的边缘,这时收缩后就可以上下台阶;先收缩是先做出上下台阶的动作,但可能存在数值相同没有上下台阶,而后用去重来保障指针真正的进行了上下台阶。
建议还是先去重,方便理解;先收缩的方法自我感觉收缩的意义变小了,虽然最后效果是相同的。
2024.02.18更
现在发现随想录上也没说什么剪枝逻辑啊哈哈哈,应该是就是去重逻辑吧,还有确实就是应该先去重后更新,先更新没啥意义;另外看了哈希的解法,第二层去重的时候确实需要思考一下。
LeetCode18. 四数之和
思路:和 15. 三数之和 一样,采用双指针的方法,多加了一层循环;
剪枝没写,暂时没写哈希表的方法。
另外比 15. 三数之和 需要多注意的是
- 这题的目标从0(确定值)变成了target(不定值),在剪枝操作上与 15. 三数之和 有区别。
- 这题在判断四数之和前要转成长整型long,不然会发生溢出(C++中int是4个字节,long是8个字节)。附上C++定义的基本整型:
类型 | 含义 | 字节数 |
---|---|---|
bool | 布尔类型(本质是整形) | 未定义 |
char | 字符 | 2 |
short | 短整形 | 4 |
int | 整形 | 4 |
long | 长整形 | 8 |
long long(C++11新增) | 长整形 | 16 |
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); i++){
if (i > 0 && 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;
}
int l = j + 1, r = nums.size() - 1;
while (l < r){
if ((long) nums[i] + nums[j] + nums[l] + nums[r] == target){
result.push_back(vector<int> {nums[i], nums[j], nums[l], nums[r]});
while (l < r && nums[l] == nums[l + 1]) l++;
while (l < r && nums[r] == nums[r - 1]) r--;
l++;
r--;
}
else if ((long) nums[i] + nums[j] + nums[l] + nums[r] < target) l++;
else r--;
}
}
}
return result;
}
};
第七天打卡,debug时思考很多,记录如上,另外有些方法(哈希表)和操作(剪枝)没写,后续有时间补全,加油!!!