454.四数相加II
给你四个整数数组 nums1
、nums2
、nums3
和 nums4
,数组长度都是 n
,请你计算有多少个元组 (i, j, k, l)
能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
将四个数组分为两组,将前两个数组之和作为key值,出现次数作为value,存入map中;
再遍历剩下的两个数组,查找map中是否存在key值满足
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
若存在就将其value值累加,最后返回计算总和即为所求。
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int,int> res;
for(int num1:nums1){
for(int num2:nums2){
res[num1+num2]++;
}
}
int sum = 0;
for(int num3:nums3){
for(int num4:nums4){
if(res.find(0-(num3+num4))!=res.end()){
sum += res[0-(num3+num4)];
}
}
}
return sum;
}
};
383. 赎金信
给你两个字符串:ransomNote
和 magazine
,判断 ransomNote
能不能由 magazine
里面的字符构成。
如果可以,返回 true
;否则返回 false
。
magazine
中的每个字符只能在 ransomNote
中使用一次
这题和有效的字母异位词类似,可以同样用数组记录每个字母出现的次数,使用一次,次数减一若数组中存在负数则表明ransomNote
不能由 magazine
里面的字符构成。
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int record[26] = {0};
if(ransomNote.size() > magazine.size())
return false;
for(int i =0; i < magazine.size(); i++){
record[magazine[i]-'a']++;
}
for(int i = 0; i < ransomNote.size(); i++){
record[ransomNote[i]-'a']--;
if(record[ransomNote[i]-'a'] < 0)
return false;
}
return true;
}
};
15. 三数之和
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请
你返回所有和为 0
且不重复的三元组
使用哈希表或者双指针的方法,对于双指针,对数组进行排序后,在一层for循环中i从下标0的地方开始,同时定一个下标left 定义在i+1的位置上,定义下标right 在数组结尾的位置上。
当三数之和小于0时,left右移,直到left>=right;
当三数之和大于0时,right左移,直到left>=right;
需要注意去重时的一些细节!!
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])//第一个元素去重,不用nums[i]==nums[i+1]是避免出现
continue; //如[-2,-2,4]之类情况
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(left<right && nums[left] == nums[left+1]) left++;
while(left<right && nums[right] == nums[right-1]) right--;
right--;
left++;
}
}
}
return result;
}
};
18. 四数之和
思路和三数之和一样,多一层for循环,注意去重和剪枝。
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(left < right){
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++;
left++;
right--;
}
}
}
}
return result;
}
};