454.四数相加II
思路:先求nums1和nums2和的种类,记录数目,用unordered_map记录。遍历得到nums3和nums4的和,回到unordered_map搜索有没有数可以凑到0。
题解:
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, int> map;
int ret{0};
for (int &num1:nums1)
{
for (int &num2:nums2)
++map[num1+num2];
}
for (int &num3:nums3)
{
for (int &num4:nums4)
{
auto it = map.find(-(num3+num4));
if (it != map.end())
ret += it -> second;
}
}
return ret;
}
};
383. 赎金信
思路:用hash表存一下ransomNote里的字母分布,遍历magazine就行。
题解:
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
unordered_map <char,int> hash;
for (char ch : ransomNote)
++hash[ch];
for (char ch : magazine)
{
if (hash.find(ch) != hash.end())
{
if (hash[ch] == 1)
hash.erase(ch);
else
--hash[ch];
}
}
return hash.empty() ? true : false;
}
};
15. 三数之和
思路:确定第一个数后,另外两个数由双指针法得到,本身不难,但是剪枝部分可能出一堆问题。我自己的话主要是两个出错了。
首先
if (i != 0 && nums[i] == nums[i-1])
这行两个条件写反了,导致越界,应该养成良好习惯,把对下标的要求尽量写在前面。
其次
while (nums[right] == nums[right-1] && left < right) right--;
while (nums[left] == nums[left+1] && left < right) left++;
在剪枝防止重复的过程中,left+1或者right-1可能就越界了,需要注意。
题解:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> ret;
for (int i = 0; i < nums.size(); ++i)
{
if (nums[i] > 0)
return ret;
if (i != 0 && nums[i] == nums[i-1])
continue;
int left = i + 1;
int right = nums.size() - 1;
while (left < right)
{
if (nums[left] + nums[right] > -nums[i])
--right;
else if (nums[left] + nums[right] < -nums[i])
++left;
else
{
vector<int> subret = {nums[i], nums[left], nums[right]};
ret.push_back(subret);
while (nums[right] == nums[right-1] && left < right) right--;
while (nums[left] == nums[left+1] && left < right) left++;
--right;
++left;
}
}
}
return ret;
}
};
18. 四数之和
思路:上一题的plus版,和上一题的注意点相同,注意一下四个数相加可能溢出,但是其实改成
nums[left] + nums[right] > target - nums[i] - nums[j]
是不会溢出的,但是四个数相加美观一点。
题解:
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
vector<vector<int>> ret;
for (int i = 0; i < nums.size(); ++i)
{
if (nums[i] > target && target > 0)
return ret;
if (i > 0 && nums[i] == nums[i-1])
continue;
for (int j = i + 1; j < nums.size(); ++j)
{
if (nums[j] == nums[j-1] && j > i + 1)
continue;
int left = j + 1;
int right = nums.size() - 1;
while (left < right)
{
if ((long)nums[left] + nums[right] + nums[i] + nums[j] > target)
--right;
else if ((long)nums[left] + nums[right] + nums[i] + nums[j] < target)
++left;
else
{
vector<int> subret = {nums[i], nums[j], nums[left], nums[right]};
ret.push_back(subret);
while (nums[right] == nums[right-1] && left < right) --right;
while (nums[left] == nums[left+1] && left < right) ++left;
++left;
--right;
}
}
}
}
return ret;
}
};