代码随想录算法训练营第六天| 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 }

 

posted @ 2023-06-13 14:50  博二爷  阅读(532)  评论(0编辑  收藏  举报