454. 四数相加 II - 力扣(LeetCode)
思路:将四个数组两两分开计算
重点:使用哈希表先记录好前两个组合的值,再通过0-(后两个组合的值)来判断是否与前两个组合匹配比如:2+1+(-1)+(-2)=0,hash[2+1]==hash[0-(-1+-2)]
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int,int>hash;
int sum=0;
for(int a:nums1){
for(int b:nums2){
hash[a+b]++;
}
}
for(int c:nums3){
for(int d:nums4){
if(hash.find(-(c+d))!=hash.end()){
sum+=hash[-(c+d)];
}
}
}
return sum;
}
};
383. 赎金信 - 力扣(LeetCode)
思路:因为ransomNote串由magazine串中的字符组成,所以当ransomNote串中出现magazine串没有的字符是表示不可以由magazine中串的字符组成,如果ransomNote串由magazine串中的字符组成表示可以由magazine中串的字符组成
重点:题目限制只有小写字母,利用数组统计magazine中每个字符的出现的次数
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int sum[26]={0};
for(char c:magazine){
sum[c-'a']++;
}
for(char c:ransomNote){
sum[c-'a']--;
if(sum[c-'a']<0){
return false;
}
}
return true;
}
};
15. 三数之和 - 力扣(LeetCode)
思路:先排序,再用三指针方式进行搜索符合要求的三元组
重点:搜索过程中注意去重,拆解先选出第一位元素,再用双指针两端进行收缩取的合适的值
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n=nums.size();
vector<vector<int>>ans;
sort(nums.begin(),nums.end());//排序默认升序
for(int i=0;i<n;i++){
if(nums[i]>0){//最小的大于零表明不可能组成比零小的三元组
return ans;
}
if(i>0&&nums[i]==nums[i-1]){//从后向前去重
continue;
}
int left=i+1;
int right=n-1;
while(left<right){
int sum=nums[i]+nums[left]+nums[right];
if(sum>0){
right--;
}else if(sum<0){
left++;
}else{
ans.push_back({nums[i],nums[left],nums[right]});
while(left<right&&nums[right]==nums[right-1]){
right--;
}
while(left<right&&nums[left]==nums[left+1]){
left++;
}
right--,left++;//收缩双指针再寻找是否有匹配的元组
}
}
}
return ans;
}
};
18. 四数之和 - 力扣(LeetCode)
思路:双指针方法嵌套三重循环,搜索符合要求的值
重点:注意去重,以及边界值判断,元素相加的时候用long long接收避免溢出
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
vector<vector<int>>ans;
int n=nums.size();
for(int a=0;a<n-3;a++){
long long x=nums[a];
if(a>0&&x==nums[a-1]) continue;//去重
if(x+nums[a+1]+nums[a+2]+nums[a+3]>target) break;
if(x+nums[n-3]+nums[n-2]+nums[n-1]<target) continue;
for(int b=a+1;b<n-2;b++){
long long y=nums[b];
if(b>a+1&&y==nums[b-1]) continue;
if(x+y+nums[b+1]+nums[b+2]>target) break;
if(x+y+nums[n-2]+nums[n-1]<target) continue;
int c=b+1,d=n-1;
while(c<d){
long long s=x+y+nums[c]+nums[d];
if(s<target)
c++;
else if(s>target){
d--;
}else {
ans.push_back({(int)x,(int)y,nums[c],nums[d]});
for(c++;c<d&&nums[c]==nums[c-1];c++);//去重
for(d--;d>c&&nums[d]==nums[d+1];d--);//去重
}
}
}
}
return ans;
}
};
总结
哈希表能很好的解决数组元素匹配的问题发现类似的题目时可以优先考虑哈希表,遇见数组需要求匹配值且改变数组不影响后续操作的时候,优先考虑将数组进行排序和利用双指针进行求解。