454. 四数相加 II

声明一个map,用来记录前两个数组中的和出现的次数

然后遍历后两个数组,如果满足后两个和与前两个和加起来为0,则次数累加

 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         unordered_map<int,int> map; //key为nums1和nums2中两个元素的和,value是出现的次数
 7         for(int i = 0; i < n; i++){
 8             for(int j = 0; j < n; j++){
 9                 map[nums1[i] + nums2[j]]++;
10             }
11         }
12 
13         for(int i = 0; i < n; i++){
14             for(int j = 0; j < n; j++){
15                 int tmp = nums3[i] + nums4[j];
16                 if(map.find(-tmp) != map.end())
17                     result+=map[-tmp];
18             }
19         }
20         return result;
21     }
22 };

383. 赎金信

建个数组,存储magazine中每个字符出现的次数

然后遍历ransomNote,如果其中字符出现的次数为0,返回false,否则数组中次数减1

 1 class Solution {
 2 public:
 3     bool canConstruct(string ransomNote, string magazine) {
 4         int arr[26];
 5         for(int i = 0; i < magazine.size(); i++){
 6             arr[magazine[i]-'a']++;
 7         }
 8         for(int i = 0; i < ransomNote.size(); i++){
 9             if(arr[ransomNote[i] - 'a'] == 0) return false;
10             arr[ransomNote[i]-'a']--;
11         }
12         return true;
13     }
14 };

15. 三数之和

先给数组排序,然后遍历数组,确定最小的元素,如果最小的元素大于0,则直接返回。如果跟上一次循环值相同,则跳过(去重)

然后使用双指针,表示其他两个数。

如果三个数的和大于0,则右指针左移。如果小于0,则左指针右移。

如果等于0,则将三元组加入result。同时过滤相同的数值,并左右指针同时收缩

 1 class Solution {
 2 public:
 3     vector<vector<int>> threeSum(vector<int>& nums) {
 4         vector<vector<int>> result;
 5         sort(nums.begin(),nums.end());
 6         for(int i = 0; i < nums.size(); i++){
 7             // 如果第一个就比0大,则直接返回
 8             if(nums[i] > 0) return result;
 9             // 去重.
10             if(i > 0 && nums[i] == nums[i - 1]) continue;
11             int l = i + 1, r = nums.size() -1;
12             while(r > l){
13                 if(nums[l] + nums[i] + nums[r] == 0){
14                     result.push_back({nums[i],nums[l],nums[r]});
15                     // 去重
16                     while(l < r && nums[l] == nums[l+1])    l++;
17                     while(l < r && nums[r] == nums[r-1])    r--;
18                     // 找到答案时同时收缩
19                     l++;
20                     r--;
21                 }else if(nums[l] + nums[i] + nums[r] > 0){
22                     // 和大于0,则右指针应该左移
23                     r--;
24                 }else{
25                     // 和小于0,则左指针应该左移
26                     l++;
27                 }
28             }
29         }
30         return result;
31     }
32 };

18. 四数之和

与上一题相比,加了一层循环,双指针表示后两个数,前面两层循环表示前两个数

 1 class Solution {
 2 public:
 3     vector<vector<int>> fourSum(vector<int>& nums, int target) {
 4         vector<vector<int>> result;
 5         sort(nums.begin(),nums.end());
 6         for(int i = 0; i < nums.size(); i++){
 7             if(nums[i] > target && nums[i] > 0) return result;
 8             // 去重
 9             if(i > 0 && nums[i] == nums[i-1])   continue;
10             for(int j = i + 1; j < nums.size(); j++){
11                 if(nums[i] + nums[j] > target && nums[i] + nums[j] >= 0) break;
12                 if(j > i + 1 && nums[j] == nums[j-1])   continue;
13                 int l = j+1,r = nums.size()-1;
14                 while(l < r){
15                     if((long)nums[i] + nums[j] + nums[l] + nums[r] > target)  r--;
16                     else if((long)nums[i] + nums[j] + nums[l] + nums[r] < target) l++;
17                     else{
18                         result.push_back({nums[i],nums[j],nums[l],nums[r]});
19                         while(l < r && nums[l] == nums[l+1])    l++;
20                         while(l < r && nums[r] == nums[r-1])    r--;
21                         l++;
22                         r--;
23                     }
24                 }
25             }
26         }
27         return result;
28     }
29 };