代码随想录算法训练营第六天| 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和
454.四数相加II
1,难点:
1,多个数组之间,会有重复出现的数组,如果单用multiset也是会出错的
2,如果用mutliset,在使用 distance 找出来 equal_range的值的时候,也是会出现奇怪的错误的
2,正确思路
1,把重复出现的节点,次数 存放到map种,然后进行遍历
3,代码:
1 int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) 2 { 3 int result = 0; 4 unordered_map<int,int> selected; 5 for (int num1 : nums1) 6 { 7 for (int num2 : nums2) 8 { 9 if (selected.find(num1 + num2) == selected.end()) 10 { 11 selected.insert(make_pair(num1 + num2, 0)); 12 } 13 selected[num1 + num2] ++; 14 } 15 } 16 17 for (int num3 : nums3) 18 { 19 for (int num4 : nums4) 20 { 21 //或许可以判断target里面有几个pair 22 auto target = selected.find(-(num3 + num4)); 23 if (target != selected.end()) 24 { 25 result += target->second; 26 } 27 } 28 } 29 30 return result; 31 }
383. 赎金信
代码
1 // 需要让ransomNote 加上一些其他的字符 == magazine 2 // 思路:用滑块的思想? 3 // 先获得 ransomNote的长度,如果<magazine -> False 4 // 然后进行双指针-》快指针找到第一个相等的节点后,我们就判断是不是一样的, 5 // 注意这个是没有顺序的 6 // 存储每一个字母对应的出现次数,然后如果他小于magazine,那么就可以 7 bool canConstruct(string ransomNote, string magazine) { 8 int ransomNoteCount[26] = {}; 9 10 for (char charItem : ransomNote) 11 { 12 ransomNoteCount[charItem - 'a']++; 13 } 14 for (char charItem : magazine) 15 { 16 ransomNoteCount[charItem - 'a']--; 17 } 18 19 for (int i : ransomNoteCount) 20 { 21 if (i > 0) 22 { 23 return false; 24 } 25 } 26 return true; 27 }
15. 三数之和
1,哈希法
难度:特别难
注意:
1,需要考虑 下标不同
2,相同下标,可出现在多个元组中
3,元组需要不一样
代码:
1 vector<vector<int>> threeSum(vector<int>& nums) { 2 vector<vector<int>> result; 3 sort(nums.begin(), nums.end()); 4 5 for (int i = 0; i < nums.size(); i++) 6 { 7 if (i > 0 && nums[i - 1] == nums[i]) 8 continue; 9 unordered_set<int> selected; 10 for (int j = i+1; j < nums.size(); j++) 11 { 12 if (j > i+2 && nums[j - 2] == nums[j - 1] && nums[j - 1] == nums[j]) 13 continue; 14 auto target = selected.find(-(nums[i] + nums[j])); 15 if (target != selected.end()) 16 { 17 result.push_back({ nums[i], nums[j], -(nums[i] + nums[j]) }); 18 selected.erase(target); 19 } 20 else 21 { 22 selected.insert(nums[j]); 23 } 24 } 25 } 26 return result; 27 }
2,双指针:
注意的点:1,left right在哪里去重
2,获得结果后 left right需要移动
代码:
1 //指针法,l r,如果 l = l+1 continue r = r-1 continue 2 vector<vector<int>> threeSum(vector<int>& nums) { 3 vector<vector<int>> result; 4 sort(nums.begin(), nums.end()); 5 6 for (int i = 0; i < nums.size(); i++) 7 { 8 if (nums[i] > 0) { 9 return result; 10 } 11 12 if (i > 0 && nums[i - 1] == nums[i]) 13 continue; 14 int left = i + 1; 15 int right = nums.size() - 1; 16 while (left < right) 17 { 18 int target = nums[i] + nums[left] + nums[right]; 19 if (target == 0) 20 { 21 result.push_back({ nums[i], nums[left],nums[right] }); 22 //应该在哪里放left移动的代码? 就是放到这里,但是需要注意 left>right 23 while (left<right&&nums[left] == nums[left + 1]) 24 left++; 25 while (left < right && nums[right] == nums[right - 1]) 26 right--; 27 28 left++; 29 right--; 30 } 31 else if (target < 0) 32 { 33 left++; 34 } 35 else if (target > 0) 36 { 37 right--; 38 } 39 } 40 41 } 42 return result; 43 }
18. 四数之和
难点:
1,需要注意剪枝,nums[i]>targeat && nums[i]>0
2,注意可能存在溢出
需要 long num[i]+... 而不是 long(num[i] ... )
代码:
1 vector<vector<int>> fourSum(vector<int>& nums, int target) 2 { 3 vector<vector<int>> result; 4 5 sort(nums.begin(), nums.end()); 6 7 for (int k = 0; k < nums.size(); k++) 8 { 9 if (nums[k] > target && nums[k] >= 0) 10 { 11 break; 12 } 13 14 if (k > 0 && nums[k] == nums[k - 1]) 15 { 16 continue; 17 } 18 19 //为什么不是nums.size()-2 20 for (int i = k + 1; i < nums.size(); i++) 21 { 22 // target>0不行么,这样的话target可能小于0 23 if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) 24 { 25 break; 26 } 27 28 if (i > k + 1 && nums[i] == nums[i - 1]) 29 { 30 continue; 31 } 32 33 int left = i + 1; 34 int right = nums.size() - 1; 35 while (right > left) 36 { 37 long sumVal = (long)nums[i] + nums[k] + nums[left] + nums[right]; 38 if (sumVal > target) 39 { 40 right--; 41 } 42 else if (sumVal < target) 43 { 44 left++; 45 } 46 else 47 { 48 result.push_back({ nums[i] , nums[k] , nums[left] , nums[right] }); 49 50 while (right > left && nums[left] == nums[left + 1]) left++; 51 while (right > left && nums[right] == nums[right - 1]) right--; 52 53 right--; 54 left++; 55 } 56 } 57 } 58 } 59 60 return result; 61 }