代码随想录算法训练营day07|454.四数相加II,383.赎金信,15.三数之和,18.四数之和
454.四数相加II
题目链接:https://leetcode.cn/problems/4sum-ii/description/
我的代码:
class Solution { public: int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) { unordered_map<int, int> map; for (int num1 : nums1) { for (int num2 : nums2) { map[num1 + num2]++; } } int sum = 0; for (int num3 : nums3) { for (int num4 : nums4) { if (map.find(0 - num3 - num4) != map.end()) { sum += map[0 - num3 - num4]; } } } return sum; } };
先两层for循环遍历数组1和数组2,再两层for循环遍历数组3和数组4,在循环中把符合的key值对应的value值加和,最终结果就是元组个数。
383.赎金信
题目链接:https://leetcode.cn/problems/ransom-note/description/
暴力解法:
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.size() == 0) return true; else return false; } };
两层for循环查找,找到后erase删除ransomNote中元素,将ransomNote中元素删光则返回true,否则返回false。
哈希解法:
class Solution { public: bool canConstruct(string ransomNote, string magazine) { if (ransomNote.size() > magazine.size()) return false; 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; } };
先比较两字符串长度,若ransomNote较长直接返回false,否则定义一个数组哈希表,索引值就是字母对于‘a’的相对位置,magazine遇字母加1,ransomNote遇字母减1,若循环结束后哈希数组内值大于0则返回true,否则直接返回false。
15.三数之和
题目链接:https://leetcode.cn/problems/3sum/description/
哈希解法(去重复杂不建议):
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[0] > 0) { break; } if (i > 0 && nums[i] == nums[i - 1]) { // 三元组元素a去重 continue; } unordered_set<int> set; for (int j = i + 1; j < nums.size(); j++) { if (j > i + 2 && nums[j] == nums[j - 1] && nums[j - 1] == nums[j - 2]) { // 三元组元素b去重 continue; } int c = 0 - nums[i] - nums[j]; if (set.find(c) != set.end()) { result.push_back({nums[i], nums[j], c}); set.erase(c); // 三元组元素c去重 } else { set.insert(nums[j]); } } } return result; } };
哈希法去重需要注意很多细节,时间复杂度也较高,不建议。
双指针解法:
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) { 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 (left < right && nums[right] == nums[right - 1]) right--; while (left < right && nums[left] == nums[left + 1]) left++; right--; left++; } } } return result; } };
三元组中元素a为nums[i],元素b为nums[left],元素c为nums[right],大体的思路是双指针向中间移动直到left>=right,其中边界条件和去重逻辑需要注意。
18.四数之和
题目链接:https://leetcode.cn/problems/4sum/description/
我的代码:
class Solution { public: vector<vector<int>> fourSum(vector<int>& nums, int target) { vector<vector<int>> result; sort(nums.begin(), nums.end()); for (int k = 0; k < nums.size(); k++) { if (nums[k] > target && nums[k] >= 0) { break; } if (k > 0 && nums[k] == nums[k - 1]) { continue; } for (int i = k + 1; i < nums.size(); i++) { if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) { break; } if (i > k + 1 && nums[i] == nums[i - 1]) { continue; } int left = i + 1; int right = nums.size() - 1; while (left < right) { if ((long)nums[k] + nums[i] + nums[left] + nums[right] > target) { // 转换为long型防止溢出 right--; } else if ((long)nums[k] + nums[i] + nums[left] + nums[right] < target) { // 转换为long型防止溢出 left++; } else { result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]}); while (left < right && nums[right] == nums[right - 1]) right--; while (left < right && nums[left] == nums[left + 1]) left++; right--; left++; } } } } return result; } };
此题和上一题思路相似,四元组中元素a为nums[k],元素b为nums[i],元素c为nums[left],元素d为nums[right],大体上是双指针向中间移动直到left>=right,其中边界条件和去重逻辑需要注意。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!