454. 四数相加 II
暴力解法(超出时间限制):
1 class Solution { 2 public: 3 int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) { 4 int n = nums1.size(); 5 int result = 0; 6 for (int i = 0; i < n; i++){ 7 for (int j = 0; j < n; j++){ 8 for (int k = 0; k < n; k++){ 9 for (int z = 0; z < n; z++){ 10 if (nums1[i] + nums2[j] + nums3[k] + nums4[z] == 0){ 11 result++; 12 } 13 } 14 } 15 } 16 } 17 return result; 18 } 19 };
哈希法:
第一步:定义一步unordered_map,key放a和b两数之和,value放a和b两数之和出现的次数;
第二步:遍历前两数组,记录两个数组元素之和以及出现的次数,umap[a+b]++;
第三步:遍历后两数组,记录(0 - (c+d))出现的次数;
第四步:count += umap[0 - (c + d)];
第五步:返回count;
1 class Solution { 2 public: 3 int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) { 4 //创建unordered_map用于保存nums1[i] + nums2[j]出现的次数 5 //key用于记录a + b的值,val用于记录a + b出现的次数 6 unordered_map<int, int> umap; 7 //用于记录a + b = - (c + d)的次数 8 int count = 0; 9 //用于记录a + b出现的次数 10 for (int a : A){ 11 for (int b : B){ 12 //记录出现次数 13 umap[a + b]++; 14 } 15 } 16 //判断c + d出现的次数 17 for (int c : C){ 18 for (int d : D){ 19 if (umap.find(0 - (c + d)) != umap.end()){ 20 count += umap[0 - (c + d)]; 21 } 22 } 23 } 24 return count; 25 } 26 };
383. 赎金信
自己写的类似242.有效的字母异位词的解法:
1 class Solution { 2 public: 3 bool canConstruct(string ransomNote, string magazine) { 4 int res[26] = {0}; 5 //记录ransomNote中字母出现的次数 6 for (int i = 0; i < ransomNote.size(); i++){ 7 res[ransomNote[i] - 'a']--; 8 } 9 //减去magazine中字母出现的次数 10 for (int i = 0; i < magazine.size(); i++){ 11 res[magazine[i] - 'a']++; 12 } 13 //判断数组中的每个数是否大于0 14 for (int i = 0; i < 26; i++){ 15 if(res[i] < 0){ 16 return false; 17 } 18 } 19 return true; 20 } 21 };
卡哥暴力解法:
1 // 时间复杂度: O(n^2) 2 // 空间复杂度:O(1) 3 class Solution { 4 public: 5 bool canConstruct(string ransomNote, string magazine) { 6 //遍历两个数组,当magazine当中出现ransomNote中的字母消去ransomNote中的该字母 7 for (int i = 0; i < magazine.length(); i++) { 8 for (int j = 0; j < ransomNote.length(); j++) { 9 // 在ransomNote中找到和magazine相同的字符 10 if (magazine[i] == ransomNote[j]) { 11 ransomNote.erase(ransomNote.begin() + j); // ransomNote删除这个字符 12 break; 13 } 14 } 15 } 16 // 如果ransomNote为空,则说明magazine的字符可以组成ransomNote 17 if (ransomNote.length() == 0) { 18 return true; 19 } 20 return false; 21 } 22 };
哈希解法:
看起来和自己写的差不多。
1 // 时间复杂度: O(n) 2 // 空间复杂度:O(1) 3 class Solution { 4 public: 5 bool canConstruct(string ransomNote, string magazine) { 6 int record[26] = {0}; 7 //add 8 if (ransomNote.size() > magazine.size()) { 9 return false; 10 } 11 for (int i = 0; i < magazine.length(); i++) { 12 // 通过recode数据记录 magazine里各个字符出现次数 13 record[magazine[i]-'a'] ++; 14 } 15 for (int j = 0; j < ransomNote.length(); j++) { 16 // 遍历ransomNote,在record里对应的字符个数做--操作 17 record[ransomNote[j]-'a']--; 18 // 如果小于零说明ransomNote里出现的字符,magazine没有 19 if(record[ransomNote[j]-'a'] < 0) { 20 return false; 21 } 22 } 23 return true; 24 } 25 };
*15. 三数之和
第一眼思路:
难度较大,没有思路,需着重学习
双指针法:
代码如下:
1 class Solution { 2 public: 3 vector<vector<int>> threeSum(vector<int>& nums) { 4 vector<vector<int>> result; 5 //对nums数组进行排序 6 sort(nums.begin(), nums.end()); 7 for (int i = 0; i < nums.size(); i++){ 8 //第一个大于零,则不存在这样的数组 9 if(nums[i] > 0){ 10 break; 11 } 12 //三元组第一个元素去重 13 if (i > 0 && nums[i] == nums[i - 1]){ 14 continue; 15 } 16 //定义双指针用于收缩 17 int left = i + 1; 18 int right = nums.size() - 1; 19 while (right > left){ 20 if (nums[i] + nums[left] + nums[right] > 0){ 21 right--; 22 } else if (nums[i] + nums[left] + nums[right] < 0){ 23 left++; 24 } else { 25 //得到结果集 26 result.push_back(vector<int>{nums[i], nums[left], nums[right]}); 27 while (right > left && nums[left] == nums[left + 1]) left++; 28 while (right > left && nums[right] == nums[right - 1]) right--; 29 //得到结果,双指针同时收缩 30 left++; 31 right--; 32 } 33 } 34 } 35 return result; 36 } 37 };
类似三数之和,利用双指针的方法,代码如下:
1 class Solution { 2 public: 3 vector<vector<int>> fourSum(vector<int>& nums, int target) { 4 vector<vector<int>> result; 5 //对nums数组进行排序 6 sort(nums.begin(), nums.end()); 7 for (int i = 0; i < nums.size(); i++){ 8 //剪枝处理 9 if(nums[i] > target && nums[i] >= 0){ 10 break; 11 } 12 //i去重 13 if(i > 0 && nums[i] == nums[i - 1]){ 14 continue; 15 } 16 for (int j = i + 1; j < nums.size(); j++){ 17 //2级剪枝操作 18 if (nums[i] + nums[j] > target && nums[i] + nums[j] >= 0) { 19 break; 20 } 21 //j去重 22 if(j > i + 1 && nums[j] == nums[j - 1]){ 23 continue; 24 } 25 int left = j + 1; 26 int right = nums.size() - 1; 27 while (right > left){ 28 if ((long)nums[i] + nums[j] + nums[left] + nums[right] < target){ 29 left++; 30 } else if ((long)nums[i] + nums[j] + nums[left] + nums[right] > target){ 31 right--; 32 } else { 33 result.push_back(vector<int>{nums[i], nums[j], nums[left], nums[right]}); 34 while (right > left && nums[right] == nums[right - 1]) right--; 35 while (right > left && nums[left] == nums[left + 1]) left++; 36 //双指针同时收缩 37 left++; 38 right--; 39 } 40 } 41 } 42 } 43 return result; 44 } 45 };
标签:ransomNote,四数,15,nums,int,随想录,++,right,left From: https://www.cnblogs.com/zsqy/p/16741982.html