454.四数相加II
刚开始想到用两个数组去分别储存其中两个数组的和,然后再将得到的两个数组求和为0时,定义一个res来存储四数之和为0的个数。但行不通,问题我也不知道在哪里。后来用哈希表去解决。将两个数组相加并存入到哈希表中,再将0减去另外两个数组的和,再哈希表中查找最终的结果。key值用来存放数值,value用来存放数值出现的个数。
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int,int> map;
int res=0;
for(int i=0;i<nums1.size();i++){
for(int j=0;j<nums2.size();j++){
map[nums1[i]+nums2[j]]++;
}
}
for(int i=0;i<nums3.size();i++){
for(int j=0;j<nums4.size();j++){
int target=0-(nums3[i]+nums4[j]);
res+=map[target];
}
}
return res;
}
};
383. 赎金信
想到用map,但是数组更简单
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
unordered_map<char,int> map1;
unordered_map<char,int> map2;
for(int i=0;i<ransomNote.size();i++){
char c = ransomNote[i];
map1[c]++;
}
for(int i=0;i<magazine.size();i++){
char c = magazine[i];
map2[c]++;
}
for (int i = 0; i < ransomNote.size(); i++) {
char c = ransomNote[i];
if (map1[c] > map2[c]) {
return false;
}
}
return true;
}
};
15. 三数之和
刚开始想用哈希表做,但是做了回好像没思路。突然想到前面类似的题,排序后使用双指针。其中的细节部分:
1.循环的条件。while(left<right&&nums[right-1]==nums[right])顺序不能反。
2.如何处理相邻数值是相等的问题。
细节挺多的,需要反复练习。
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;
}
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)
{
res.push_back({nums[i],nums[left],nums[right]});
while(left<right&&nums[left+1]==nums[left]) left++;
while(left<right&&nums[right-1]==nums[right]) right--;
left++;
right--;
}
else if(nums[i]+nums[left]+nums[right]>0) {
right--;
}
else{
left++;
}
}
}
return res;
}
};
18. 四数之和
有了三数之和后,四数之和采用相同的办法也可以解决。
其中要注意的问题:
1.剪枝问题。if(nums[i]>target&&nums[i]>=0){ break;} 这里和三数之和不一样,不确定target的值。所以不能用nums[i]>0去判断。
2.有些案例数组数值大,导致相加后数值越界加一个(long)去处理。
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;
}
if(i>0&&nums[i]==nums[i-1]){
continue;
}
for(int next=i+1;next<nums.size();next++){
if(nums[i] + nums[next] > target && nums[i] + nums[next] >= 0){
break;
}
if(next>i+1&&nums[next]==nums[next-1]) continue;
int left=next+1;
int right=nums.size()-1;
while(left<right){
if((long)nums[i]+nums[next]+nums[left]+nums[right]==target)
{
res.push_back({nums[i],nums[next],nums[left],nums[right]});
while(left<right&&nums[left]==nums[left+1]) left++;
while(left<right&&nums[right]==nums[right-1]) right--;
left++;
right--;
}
else if((long)nums[i]+nums[next]+nums[left]+nums[right]>target) {
right--;
}
else{
left++;
}
}
}
}
return res;
}
};