一、LeetCode454 四数相加Ⅱ
题目链接:454. 四数相加 II - 力扣(LeetCode)
1.看到题目第一下想法
首先考虑与四数之和的区别,首先此题目与三数之和、四数之和不同点在于是从不同的数组集合中选取元素,并且构成元组的元素是下标i、j、k、l并不是数组元素本身,所以使用哈希表不用考虑去重的问题,例如虽然1 -2 2 -1 与2 -1 1 -2 元素相同,但是返回的元组是其下标值,最终还是不同的。
2.实现过程中遇到的问题
(1)注意此时哈希表选用map以及key、value的含义,key指的前两个的和的值,value指的是出现的次数,所以在使用哈希表的时候map[nums[i]+nums[j]]而不是map[i+j]这是写错的地方
3.代码
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 i=0;i<nums1.size();i++){
for(int j=0;j<nums2.size();j++){
map[nums1[i]+nums2[j]]++; //sum[i+j]不对
}
}
for(int i=0;i<nums3.size();i++){
for(int j=0;j<nums4.size();j++){
if(map.find(0-(nums3[i]+nums4[j]))!=map.end()){
count += map[(0-(nums3[i]+nums4[j]))];
}
}
}
return count;
}
};
//整体思路,四树之和分为两组,前两个相加为一个数放入到哈希表中去,然后将后两个相加,然后在哈希表中寻找0-后两个之和是否出现过
//注意哈希表中,key与value分别代表什么
//此题目无需考虑去重
4.总结
主要是思路:首先理解为什么不需要去重,然后利用哈希表存储前两个元素的和,再遍历后两个元素,在哈希表中寻找有没有后两个元素和的相反数,并加入计数count
二、LCR007 三数之和
题目链接:LCR 007. 三数之和 - 力扣(LeetCode)
1.看到题目第一下想法
此题目与四数相加不同,会涉及到去重问题,所以简单的哈希表很复杂,需要换一种方法
2.实现过程中遇到的问题
主要是整体代码框架,明确使用双指针方法,在双指针方法的基础上加上排序、剪枝、去重操作。
首先排序sort(nums.begin(),nums.end());然后开始遍历i,完成剪枝操作;然后开始对i去重,注意此处去重的条件判断,两种条件,i= i+1是不合理的,这样去掉了i= left的一种情况;然后进入双指针法,定义双指针,开始判断,在找到一个答案之后,要对双指针进行去重,注意对双指针去重的时机,一定是在找到第一个答案之后去重,否则(0000)这种情况将被遗漏,最后返回结果。
3.代码
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){
break; //与return result有什么区别
}
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{
result.push_back(vector<int>{nums[i], nums[left], nums[right]});
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
right--;
left++;
}
}
}
return result;
}
};
//双指针法 i left right 并对这三个都需要去重
//剪枝与去重
//去掉一些不合理的情况:排序之后i>0
//去重:对i去重,两种情况 i=i+1 i=i-1 应该选第二种,第一种将000这种情况去除掉了
//开始循环,注意循环终止的条件
//对left right去重,必须在收获一次结果后去重,还是举例000000,如果一开始去重,那么将不会收获到结果
4.总结
排序、剪枝、对i去重、循环、双指针去重
三、LeetCode18 四数之和
1.看到题目第一下想法
在三数之和的基础上再套一层循环,首先遍历i,剪枝,去重,然后遍历j,剪枝,去重,进入双指针法
2.实现过程中遇到的问题
(1)整体实现逻辑:外层剪枝、去重;内层剪枝、去重;双指针、双指针去重
(2)在完成双指针判断时,出现整数溢出的情况,进行强制类型转换为long
3.代码
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
for(int i=0;i<nums.size();i++){
if(nums[i]>target&&nums[i]>=0){
break;
}
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;
}
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{
result.push_back(vector<int>{nums[i], nums[j],nums[left], nums[right]});
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
right--;
left++;
}
}
}
}
return result;
}
};
//剪枝的条件
//区分三数之和与四数之和的区别 在条件上的确立
//整理思路:一级剪枝、一级去重(i)、二级剪枝、二级去重(j)、双指针循环、得到结果、双指针去重
//比三数之和多一层循环
//Line 19: Char 46: runtime error: signed integer overflow: 2000000000 + 1000000000 cannot be represented in type 'value_type' (aka 'int') (solution.cpp)
//SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:28:46
//如果不加(long)会导致整数溢出
4.总结
(1)排序、剪枝、去重、双指针
(2)整数溢出,使用强制类型转换为long
四、LeetCode383 赎金信
1.看到题目第一下想法
两个字符串,本质其实就是是否为字母异位词,同理,用数组形式的哈希表去解决即可
2.实现过程中遇到的问题
主要是看清题目本质
3.代码
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
if(ransomNote==magazine){
return true;
}
if(ransomNote.size()>magazine.size()){
return false;
}
//相当于字母异位词
int nums[26]={0};
for(int i=0;i<ransomNote.size();i++){
nums[ransomNote[i]-'a']++;
}
for(int j=0;j<magazine.size();j++){
nums[magazine[j]-'a']--;
}
for(int i=0;i<26;i++){
if(nums[i]>0){
return false;
}
}
return true;
}
};
//居然没看出来是字母异位词 太蠢了
4.总结
看清题目本质