DAY7 - 454.四数相加II, 383.赎金信, 15.三数之和, 18.四数之和
454.四数相加II
和昨天那个两数之和为target有点像。
一开始想的是创建四个map分别存数组,但是这样跟暴力算法也没区别。
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 n1:nums1){
for(int n2:nums2){
int sum=n1+n2;
auto a=map.find(sum);
if(a==map.end()){
map.insert({sum,1});
}else{
a->second++;
}
}
}
for(int n3:nums3){
for(int n4:nums4){
auto a=map.find(-n3-n4);
if(a!=map.end()){
res+=a->second;
}
}
}
return res;
}
};
小tips:
- 设置
auto a=map.find(sum);在后面要a->second++;的时候可以避免重复计算,降低时间复杂度。 - 计算结果数量的时候
res+=a->second;,不能只加一次。
383.赎金信
一开始想到的省事的办法是用unorderd_map,但是题解里面说用um要维护哈希表还有使用哈希函数,费时间,在数据量大的时候更耗时,所以还是使用数组。
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int m[26]={0};
for(char c:magazine){
m[c-'a']++;
}
for(char c:ransomNote){
if(--m[c-'a']<0) return false;
}
return true;
}
};
可以在代码最前面加上一个判断,减少无用操作,提升运行速度
if (ransomNote.size() > magazine.size()) {
return false;
}
15.三数之和
尝试使用哈希。
要去重的话一个通用思路是要排序,这样才能把一样的元素放在一起。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<vector<int>> res;
for(int i=0;i<nums.size();i++){
if(nums[i]>0) break;
if(i>0&&nums[i]==nums[i-1]) continue; //去重
unordered_set<int> set;
for(int j=i+1;j<nums.size();j++){
//去重b=c时的情况
if (j>i+2 && nums[j]==nums[j-1] && nums[j-1]==nums[j-2]) continue;
int target=0-nums[i]-nums[j];
if(set.find(target)!=set.end()){
res.push_back({nums[i],nums[j],target});
set.erase(target);//去重
}else{
set.insert(nums[j]);
}
}
}
return res;
}
};
这个去重b==c时候的条件比较难想,还有这个set.erase(target)
通过了但是程序执行时间很长。
双指针写法执行时间快了不少,而且内存消耗也更低。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<vector<int>> res;
for(int i=0;i<nums.size();i++){
if(nums[i]>0) break;
if(i>0&&nums[i]==nums[i-1]) continue;
int left=i+1;
int right=nums.size()-1;
while(left<right){
int sum=nums[i]+nums[left]+nums[right];
if(sum==0){
res.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++;
left++;
right--;
}else if(sum>0) right--;
else left++;
}
}
return res;
}
};
18.四数之和
在一个数组内并且要求去重,和三数之和比较像,考虑用双指针,for循环写两层。
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
vector<vector<int>> res;
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 j=i+1;j<nums.size();j++){
if(nums[i]+nums[j]>target&&nums[i]+nums[j]>=0) break;
if(j>i+1&&nums[j]==nums[j-1]) continue;
int left=j+1;
int right=nums.size()-1;
while(left<right){
long sum=(long)nums[i]+nums[j]+nums[left]+nums[right];
if(sum==target){
res.push_back({nums[i],nums[j],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(sum<target) left++;
else right--;
}
}
}
return res;
}
};
- 注意内层循环
if(j>i+1&&nums[j]==nums[j-1]) continue;要和三数之和用哈希法if (j>i+2 && nums[j]==nums[j-1] && nums[j-1]==nums[j-2]) continue;区分。j只要管好自己不要重复就行了。 long sum=(long)nums[i]+nums[j]+nums[left]+nums[right];提交时提示sum会溢出,所以用long
浙公网安备 33010602011771号