454. 四数相加 II
暴力是n四次方,但是我们可以划分为两个n的平方的削减时间复杂度
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
map<int, int> hash_1; // 键:值, 值:出现次数
map<int, int> hash_2;
for (int i = 0; i < nums1.size(); i++)
{
for (int j = 0; j < nums2.size(); j++)
{
int temp = nums1[i] + nums2[j];
if (hash_1.count(temp) == 0)
hash_1.insert({temp, 1}); // 没有就添加
else
hash_1[temp]++; // 有就加一个
}
}
for (int i = 0; i < nums3.size(); i++)
{
for (int j = 0; j < nums4.size(); j++)
{
int temp = nums3[i] + nums4[j];
if (hash_2.count(temp) == 0)
hash_2.insert({temp, 1}); // 没有就添加
else
hash_2[temp]++; // 有就加一个
}
}
int res = 0;
for (auto i : hash_1)
{
int num_1 = 0 - i.first; // 前两个数组的倒数,用来找互补
auto it_2 = hash_2.find(num_1);
if (it_2 != hash_2.end())
{
res += it_2->second * i.second;
}
}
return res;
}
};
383. 赎金信
这题跟242. 有效的字母异位词差不多,哈希简单映射一下,计数一下就完事了
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
map<int, int> hash; // 键:字符, 值:字符出现的次数
for (auto i : magazine)
{
hash[i]++;
}
for (auto i : ransomNote)
{
auto it = hash.find(i);
if (it != hash.end()) // 代表有可以用来替换的字符,但多少不知道
{
it->second--;
if (it->second == 0)
hash.erase(it); // 为0了,代表没有了
}
else
{
return false;
}
}
return true;
}
};
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)
return res;
// 对 i 进行去重
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int left = i + 1, 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 {
res.push_back(vector<int>{nums[i], nums[left], nums[right]});
// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
// 找到答案时,双指针同时收缩
right--;
left++;
}
}
}
return res;
}
};
18. 四数之和
和三数之和类似,不过多了一个指针,先排序,然后固定两个指针,然后进行双指针遍历,去重
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] >= 0 && nums[i] > target)
{
break;
}
if (i > 0 && nums[i] == nums[i - 1])
continue;;
for (int j = i + 1; j < nums.size(); j++)
{
if (nums[i] + nums[j] >= 0 && nums[i] + nums[j] > target)
{
break;
}
if (j > i + 1 && nums[j] == nums[j - 1])
continue;
int l = j + 1, r = nums.size() - 1;
while (l < r)
{
if ((long) nums[i] + nums[j] + nums[l] + nums[r] > target)
r--;
else if((long) nums[i] + nums[j] + nums[l] + nums[r] < target)
l++;
else
{
res.push_back({nums[i], nums[j], nums[l], nums[r]});
while (r > l && nums[r] == nums[r - 1]) r--;
while (r > l && nums[l] == nums[l + 1]) l++;
l++;
r--;
}
}
}
}
return res;
}
};