454. 四数相加 II
题目链接:454. 四数相加 II
![在这里插入图片描述](https://img-blog.csdnimg.cn/7251fd996978444db014586e7bbf2791.png#pic_center)
题解:
- 四个数组是独立的,不用考虑去重;
- 首先定义一个unordered_map,key:a+b,value:a+b之和出现的次数;
- 遍历nums1和nums2,统计a+b之和出现的次数,放入map中;
- 定义一个target,用来匹配c+d,即target = 0-(c+d);
- 遍历nums3和nums4,统计和c+d匹配的target个数,即sum += map[target],这里map[target]是target所对应的value值;
- 最后返回sum;
代码
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int,int> map;
int sum=0;
for(int a:nums1){
for(int b:nums2){
map[a+b]++;
}
}
for(int c:nums3){
for(int d:nums4){
int target = 0-(c+d);
if(map.find(target) != map.end()){
sum += map[target];
}
}
}
return sum;
}
};
383. 赎金信
题目链接:383. 赎金信
![在这里插入图片描述](https://img-blog.csdnimg.cn/86674dddd690440da8609cfc90618b52.png#pic_center)
题解:
- 由于字符串中都是小写字符,定义一个hash数组,初始化为0;
- if(ransomNote.size() > magazine.size()) return false;
- 遍历magazine,统计出现字符的个数;
- 遍历ransomNote,减去出现字符的个数,如果字符个数<0,return false;
- 如果可以顺利走出for循环,即符合题意;
代码
哈希解法
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int hash[26] = {0};
if(ransomNote.size() > magazine.size()) return false;
for(int m=0; m<magazine.size(); m++){
hash[magazine[m]-'a']++;
}
for(int r=0; r<ransomNote.size(); r++){
hash[ransomNote[r]-'a']--;
if(hash[ransomNote[r]-'a'] < 0) return false;
}
return true;
}
};
15. 三数之和
题目链接:15. 三数之和
![在这里插入图片描述](https://img-blog.csdnimg.cn/a63366cd854b4963ad7228607b3fd61e.png#pic_center)
题解:
- 使用双指针的话要先对数组nums排序,即sort(nums.begin(), nums.end());
- 遍历排序后的nums数组,a为nums[i],b为 nums[left],c为nums[right];
- 如果nums[i]已经>0了,则找不到匹配的b和使得a+b+c==0,直接return;
- 因为是找三个数,所以left一定不能等于right,即while(left<right);
- 如果nums[i] + nums[left] + nums[right] > 0说明此时三数之和大了,right向左移动;
- 如果 nums[i] + nums[left] + nums[right] < 0说明此时三数之和小了,left 向右移动;
- 时间复杂度:O(n^2);
代码
双指针法
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(nums[i] > 0) return result;
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{
result.push_back(vector<int>{nums[i],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;
}
};
18. 四数之和
题目链接:18. 四数之和
![在这里插入图片描述](https://img-blog.csdnimg.cn/06ea6f3d492b48d5ae2f9371e131b405.png#pic_center)
代码
双指针法
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;
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;
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]});
while(right>left && nums[right] == nums[right-1]) right--;
while(right>left && nums[left] == nums[left+1]) left++;
right--;
left++;
}
}
}
}
return result;
}
};