Leetcode 454. 四数相加 II
思路:注意这一题是四个不同的数组,并且4个元素可以是相同的,相对来讲会好做一点。遍历nums1
和nums2
,得到元素之和a+b
,并统计a+b
出现的次数,同理遍历nums3
和nums4
,判断元素之和是否为0-(a+b)
,如果存在,则加上a+b
出现的次数。
需要保存两个数据:a+b
的值和出现的次数,所以使用unordered_map
来存放数据
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int,int> map; //key是a+b的值 value是a+b出现的次数
int cnt = 0;
for(int a:nums1){
for(int b:nums2)
map[a+b]++;
}
for(int c:nums3){
for(int d:nums4){
if(map.find(0-c-d) != map.end()) //如果找到对应的key
cnt+=map[0-c-d]; //加上value 即0-c-d出现的次数
}
}
return cnt;
}
};
Leetcode 383. 赎金信
思路:用一个数组统计magazine
里每个字母出现的频率,并统计ransomNote
里每个字母出现的次数,如果数组中有元素<0
,则说明ransomNote
含有magazine
中没有的字母,输出false
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 i=0;i<ransomNote.size();i++){
a[ransomNote[i]-'a']--;
if(a[ransomNote[i]-'a']<0) //小于0说明有字符magazine没有 说明不能构成ransomNote
return false;
}
return true;
}
};
Leetcode 15. 三数之和
思路:先给数组排序,如果第i
个元素大于0则直接return
,即剪枝操作。然后使用双指针法,外面一层for循环,i
下标从0开始,里面是双指针,left
下标从i+1
开始,right
下标从数组最后一个元素开始。判断nums[i]+nums[left]+nums[right]
与0的关系。
因为题目说了不可以包含重复的三元组,注意要对nums[i]、nums[left]、nums[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) //如果a大于0 则不存在满足条件的三元组
return result;
if(i>0 && nums[i]==nums[i-1]) //对a去重
continue;
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(right>left && nums[left]==nums[left+1])left++; //对b和c去重
while(right>left && nums[right]==nums[right-1])right--;
left++;
right--; //找到答案时左右指针同时收缩
}
}
}
return result;
}
};
Leetcode 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--; //用long long防止溢出
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(left<right && nums[left+1]==nums[left])left++;
while(left<right && nums[right-1]==nums[right])right--;
left++;
right--;
}
}
}
}
return result;
}
};