代码随想录算法训练营第七天|第454题.四数相加II,383. 赎金信,第15题. 三数之和
第454题.四数相加II
文章链接:https://programmercarl.com/0454.四数相加II.html
视频讲解:https://www.bilibili.com/video/BV1Md4y1Q7Yh/
题目链接:https://leetcode.cn/problems/4sum-ii/description/
题目思路:
- 首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
- 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
- 定义int变量count,用来统计 a+b+c+d = 0 出现的次数。
- 再遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
- 最后返回统计值 count 就可以了
总结:map中key存a+b的和,value存出现该key的次数。
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 num1:nums1){
for(int num2:nums2){
map[num1+num2]++;
}
}
for(int num3:nums3){
for(int num4:nums4){
if(map.find(0-num3-num4)!=map.end()){ //如果找到了
count+=map[0-num3-num4];
}
}
}
return count;
}
};
383. 赎金信
文章链接:https://programmercarl.com/0383.赎金信.html#思路
题目链接:https://leetcode.cn/problems/ransom-note/description/
总结:这里我用的是哈希表,但其实在本题的情况下,使用map的空间消耗要比数组大一些的,因为map要维护红黑树或者哈希表,而且还要做哈希函数,是费时的!数据量大的话就能体现出来差别了。 所以数组更加简单直接有效!
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
unordered_map<char,int> map; //key为出现的字符,value为字符的数量
for(int i=0;i<magazine.size();i++){
map[magazine[i]]++;
}
for(int j=0;j<ransomNote.size();j++){
if(map.find(ransomNote[j])!=map.end()){ //如果找到了
int num=map.find(ransomNote[j])->second;
if(num>0) map[ransomNote[j]]--;
else return false;
}
else return false; //如果没找到,返回false
}
return true;
}
};
第15题. 三数之和
文章链接:https://programmercarl.com/0015.三数之和.html
视频链接:https://www.bilibili.com/video/BV1GW4y127qo/?vd_source=6cb513d59bf1f73f86d4225e9803d47b
题目链接:https://leetcode.cn/problems/3sum/description/
双指针法总结:
- 首先对数组进行排序(为了方便进行后续的操作判断)
- 如果将得到的结果按照非降序的顺序表示为
- 首先对a进行去重(因为如果是非降序的,那么就有可能会有连续的一样的a值,eg.
-1,-1
,0,1,2。但一个a值就是我们统计的其中一种方案,必然导致重复) - 接着对b和c进行去重(因为可能会导致如下情况:eg.-1,
-2,-2
,0,0,3,3
)
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++){ //i从0开始遍历整个nums数组
if(nums[i]>0) return res;
//去重a;
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) right--;
else if(nums[i]+nums[left]+nums[right]<0) left++;
else{
res.push_back(vector<int>{nums[i],nums[left],nums[right]});
//找到一个可能值之后去重b,c
while(left<right&&nums[left]==nums[left+1]) left++;
while(left<right&&nums[right]==nums[right-1]) right--;
//去重后,到下一个待判断的点
left++;
right--;
}
}
}
return res;
}
};
分类:
代码随想录算法训练营
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!