454.四数相加Ⅱ
题目链接:https://leetcode.cn/problems/4sum-ii/
文章讲解:https://programmercarl.com/0454.%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0II.html
视频讲解:https://www.bilibili.com/video/BV1Md4y1Q7Yh
状态:不会
思路
可以结合有效的字母异位词、两数之和两道题目的思想。每次遇到一个元素,在数组里找到一个对应的位置+1,两数之后是装入map,然后去找另一个数组每个元素,用target减去当前第二个数组的元素。
本题的话,四数相加可以搞成两个数之和,每两个两个的去循环,把前两个的和装入map,每次在对应位置加1,遍历后两个数组的和的时候,用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 count = 0;
for(int num1 : nums1){
for(int num2 : nums2){
map[num1 + num2] ++;
}
}
for(int num3 : nums3){
for(int num4 : nums4){
int target = 0 - (num3 + num4);
auto iter = map.find(target);
if(iter != map.end()){
count += iter -> second;
//count += map[target];
}
}
}
return count;
}
};
383.赎金信
题目链接:https://leetcode.cn/problems/ransom-note/
文章讲解:https://programmercarl.com/0383.%E8%B5%8E%E9%87%91%E4%BF%A1.html
状态:做了出来
思路
自己看到题目的第一想法:
我先用hash数组试了一下,结果不会处理,然后用map成了,关于map,就是把magazine的元素存储在map中,然后在遍历ransomNote时,去在map查找,若找到就-1,并不时的判断是否小于等于0了
看完代码随想录的想法:
在用hash数组,其实造搬map就可以了
注意:有同时需要下标和数值用map;或者数值很大很分散用map
代码实现
①双层for循环,注意erase的用法
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
for(int i = 0; i < magazine.size(); i++){
for(int j = 0; j < ransomNote.size(); j++){
if(ransomNote[j] == magazine[i]){
ransomNote.erase(ransomNote.begin() + j);
break;
}
}
}
if(ransomNote.length() != 0) return false;
return true;
}
};
②哈希
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
vector<int> hash(26, 0);
for(int i = 0; i < magazine.size(); i++){
hash[magazine[i] - 'a'] ++;
}
for(int i = 0; i < ransomNote.size(); i++){
hash[ransomNote[i] - 'a'] --;
}
for(int i = 0; i < 26; i++){
if(hash[i] < 0) return false;
}
return true;
}
};
三数之和
题目链接:https://leetcode.cn/problems/3sum/
文章讲解:https://programmercarl.com/0015.%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C.html
视频讲解:https://www.bilibili.com/video/BV1GW4y127qo
状态:不会
思路
采用相向双指针法,每次判断i,left,right下标的元素和与0比较,大于0 就right–,小于0就left++;
其实本题最大的难点在于如何去重,我们要去重,就要对i,left,right三者都去重。
在对i去重的时候,有nums[i]==nums[i+1]和nums[i]==nums[i-1],为什么用后一种呢?因为,有类似[-1,-1,2]这样的解,用第一种显然不行
在对left和right去重的时候,可以用nums[left]==nums[left+1],而不能用第二种
本题还有哈希的解法,但是比较麻烦,我这里就不学习了
代码实现
注意vector.push_back的使用
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); i++){
if(nums[i] > 0) return res;
if(i > 0 && nums[i] == nums[i - 1]) 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{
res.push_back(vector<int>{nums[i], nums[left], nums[right]});
while(left < right && nums[left] == nums[left + 1]) left ++;
while(left < right && nums[right] == nums[right - 1]) right --;
left++;
right--;
}
}
}
return res;
}
};
18.四数之和
题目链接:https://leetcode.cn/problems/4sum/
文章讲解:https://programmercarl.com/0018.%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C.html
视频讲解:https://www.bilibili.com/video/BV1DS4y147US
状态:细节没处理好,没做出来
思路
仿造三数之和去做就Ok了,只不过这里需要注意,taget不是0,所以剪枝的时候要加上target>0的条件,还有就是j的去重,要注意j从i+2开始
代码实现中的困难
自己老是忘记 i要大于0,以及最后的left++和right–要在while循环里
代码实现
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); i++){
if(nums[i] >= 0 && nums[i] > target) break;//也可return res
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;//return res;会报错
if(j > i + 1 && nums[j] == nums[j - 1]) continue;
int left = j + 1;
int right = nums.size() - 1;
while(left < right){
if((long)nums[i] + nums[j] + nums[left] + nums[right] > target) {right --;}
else if((long)nums[i] + nums[j] + nums[left] + nums[right] < target) {left ++;}
else{
res.push_back(vector<int>{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 --;
}
}
}
}
return res;
}
};
收获
用map的条件一时要下标,一是key值很大很分散
如何去重