今日任务
- 454.四数相加II
- 383. 赎金信
- 15. 三数之和
- 18. 四数之和
- 总结
一、四数相加II
题目解读:本体较为简单的一点在于它是四个独立的数组,所以可以用到map去做。思路就是遍历找a+b的和记录在map中,再找c+d取相反数在和map中找对应的key,count就加上其value。
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int,int> map;
for(int a:nums1){
for(int b:nums2){
map[a+b]++;
}
}
int count = 0;
for(int c:nums3){
for(int d:nums4){
if(map.find(0-c-d)!=map.end()){
count+= map[0-c-d];
}
}
}
return count;
}
};
思路明确之后就没出啥毛病,确实感觉对哈希表有些精进。
二、赎金信
题目解读:感觉是比较简单的,和昨天第一道题是差不多的。
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int a[26] = {0};
for(int i = 0;i<magazine.size();i++){
a[magazine[i]-'a']++;
}
for(int j=0;j<ransomNote.size();j++){
a[ransomNote[j]-'a']--;
}
for(int i = 0 ;i<26;i++){
if(a[i]<0){
return false;
}
}
return true;
}
};
也算是一遍就过了,思路没问题确实还是蛮快的,但还有一些可以改进的地方,比如目标串大小大于参考串,此时可以直接返回错误,因为完全匹配也满足不了。
三、三数之和
题目解读:由于是答案中不能包含重复元素,所以如果用哈希可能在剪枝中超时,也自己尝试写了一些,感觉还是挺困难的。
所以最终还是看题解用双指针。
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){
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++;
}
else if(nums[i] + nums[left]+nums[right]>0){
right--;
}
else{
left++;
}
}
}
return result;
}
};
中间有出现思路不太清晰的情况,剪枝也有些没有想到,但还是写出来了。
本体还是要注意剪枝逻辑,尤其是要比较num[i]和num[i-1];
四、四数之和
题目解读:四数之和和三数之和基本相同,就是剪枝需要更多注意。
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(nums[i]>target&&nums[i]>=0){
break;
}
if(i>0&&nums[i]==nums[i-1]){
continue;
}
for(int k=i+1;k<nums.size();k++){
if(nums[i]+nums[k]>target&&nums[i]+nums[k]>=0){
break;
}
if(k>i+1&&nums[k]==nums[k-1]){
continue;
}
int left = k+1;
int right = nums.size()-1;
while(right>left){
if((long)nums[i]+nums[k]+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;
}
};
基本思路对的情况下还有比较多的细节需要处理。
五、总结
一般来说哈希表都是用来快速判断一个元素是否出现集合里。
总共花了一个半小时,感觉哈希表有些进步。