训练营打卡Day07
文章目录
题19:454. 四数相加 II
思路
- 用两个map分别承载两组的和,与出现过的次数
- 再遍历两个map, 将和为0的次数相加
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, int>m1, m2;
for(const auto& num1: nums1)
for(const auto& num2: nums2)
{
m1[num1+num2]++;
}
for(const auto& num3: nums3)
for(const auto& num4: nums4)
{
m2[num3+num4]++;
}
int count = 0;
for(auto val1 : m1)
for(auto val2 : m2)
{
if(val1.first+val2.first == 0)
count += val1.second*val2.second;
}
return count;
}
};
题20:383. 赎金信
思路
- 用一个map来统计magazine中字母出现的频次
- 再用map来减去ransomNote,字母出现的频次
- 当map当中有字母频次有负数时,则return false
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
vector<int>dic(26, 0);
for(const char& ch1: magazine)
dic[ch1 - 'a']++;
for(const char& ch2: ransomNote)
{
dic[ch2 - 'a']--;
if(dic[ch2 - 'a'] < 0) return false;
}
return true;
}
};
题21:15. 三数之和
思路
用双指针法
- 首先将数组排序,从大到小
- 三个数,左中右,i为左,遍历,left为重,right为右,
- 去重在于,i与i+1, left与left+1, right与right-1
- 三个数的和sum,
- sum > 0 , right–
- sum < 0 , left++
- sum == 0 ,获取结果,left与left+1, right与right-1 ,去重后,还需要right–, left++
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() - 3; i++)
{
if(nums[i] > 0) return result;
if(i > 0 && nums[i-1] == nums[i]) continue;
int left = i+1, right = nums.size() - 1;
while(left < right)
{
int sum = nums[i] + nums[left] + nums[right];
if(sum > 0)
{
right--;
}
else if(sum < 0)
{
left++;
}
else
{
result.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--;
}
}
}
return result;
}
};
题22:18. 四数之和
思路
延续三数之和的思路,在外面套了一层for循环。
剪枝
target可能是正数,也可能是负数
if(nums[k] > target && (nums[k] >= 0 || target >= 0))
if(nums[k] + nums[i] > target && (nums[k] + nums[i] >= 0 || target >= 0))
去重
if(k>0 && nums[k] == nums[k-1])
if(i > k + 1 && nums[i] == nums[i-1])
注意
不要轻易return result, 要用break.
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 || target >= 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 || target >= 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 (nums[k] + nums[i] > target - (nums[left] + nums[right]))
{
right--;
while(left < right && nums[right+1] == nums[right]) right--;
}
else if (nums[k] + nums[i] < target - (nums[left] + nums[right]))
{
left++;
while(left < right && nums[left-1] == nums[left]) left++;
}
else
{
result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
right--;
while(left < right && nums[right+1] == nums[right]) right--;
left++;
while(left < right && nums[left-1] == nums[left]) left++;
}
}
}
}
return result;
}
};