文章链接:代码随想录 (programmercarl.com)
视频链接:代码随想录算法公开课 | 最强算法公开课 | 代码随想录
笔记
- 当map内元素值为int类型或常量时,默认值为0。
- 难点在于将数组分成两类处理,降低时间复杂度
C++代码
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]++;//记录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;//返回的是次数,所以可以用哈希法
}
};
文章链接:代码随想录 (programmercarl.com)
笔记
C++代码
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int rec[26]={0};
//直接判断
if (ransomNote.size() > magazine.size()) {
return false;
}
for(int i=0;i<magazine.size();i++){
rec[magazine[i]-'a']++;
}
for(int j=0;j<ransomNote.size();j++){
rec[ransomNote[j]-'a']--;
}
for(int i=0;i<26;i++){
if(rec[i]<0){
return false;
}
}
return true;
}
};
文章链接:代码随想录 (programmercarl.com)
视频链接:代码随想录算法公开课 | 最强算法公开课 | 代码随想录
笔记
- 关键在去重逻辑以及是否能想到双指针的方法
- 由于并未要求输出下标,可进行初步排序
C++代码
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;
}
// 对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[right]+nums[left]==0){
res.push_back(vector<int>{nums[i],nums[left],nums[right]});
right--;
left++;
//去重b,c
while(left<right && nums[right]==nums[right+1])right--;
while(left<right && nums[left]==nums[left-1])left++;
}else if(nums[i]+nums[left]+nums[right]>0){
right--;
}else if(nums[i]+nums[left]+nums[right]<0){
left++;
}
}
}
return res;
}
};
文章链接:代码随想录 (programmercarl.com)
视频链接:代码随想录算法公开课 | 最强算法公开课 | 代码随想录
笔记
- 在三数之和的基础上实现四数之和
- 去重i,j时应考虑target为负
C++代码
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;//后半段是因为target为负数时,前半部分的条件不能剪枝
if(i>0 && nums[i]==nums[i-1])continue;
for(int j=i+1;j<nums.size();j++){
int add=nums[i]+nums[j];
if(add>target && add >= 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)add+nums[left]+nums[right]>target){//long
right--;
}else if((long)add+nums[left]+nums[right]<target){
left++;
}else{
res.push_back(vector<int>{nums[i],nums[j],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;
}
};