• 代码随想录算法训练营第23期day7| 454.四数相加II 、383. 赎金信 、15. 三数之和、18. 四数之和


    目录

    一、(leetode 454)四数相加II

    二、(leetcode 383)赎金信

    暴力解法

    哈希法 

    三、(leetcode 15)三数之和

    四、(leetcode 18)四数之和


    一、(leetode 454)四数相加II

    力扣题目链接

    状态:已AC。搞懂了key、value的意义了

    1. class Solution {
    2. public:
    3. int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
    4. unordered_map<int, int> umap; //key:a+b的数值,value:a+b数值出现的次数
    5. for (int a :nums1) {
    6. for (int b : nums2) {
    7. umap[a + b]++;
    8. }
    9. }
    10. int count = 0; // 统计a+b+c+d = 0 出现的次数
    11. // 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。
    12. for (int c : nums3) {
    13. for (int d : nums4) {
    14. if (umap.find(0 - (c + d)) != umap.end()) {
    15. count += umap[0 - (c + d)];
    16. }
    17. }
    18. }
    19. return count;
    20. }
    21. };

    二、(leetcode 383)赎金信

    力扣题目链接

    状态:哈希法AC(类似242.有效的字母异位词),暴力法不熟悉erase用法,只了解了思路

    暴力解法

    1. class Solution {
    2. public:
    3. bool canConstruct(string ransomNote, string magazine) {
    4. for (int i = 0; i < magazine.length(); i++) {
    5. for (int j = 0; j < ransomNote.length(); j++) {
    6. // 在ransomNote中找到和magazine相同的字符
    7. if (magazine[i] == ransomNote[j]) {
    8. ransomNote.erase(ransomNote.begin() + j); // ransomNote删除这个字符
    9. break;
    10. }
    11. }
    12. }
    13. // 如果ransomNote为空,则说明magazine的字符可以组成ransomNote
    14. if (ransomNote.length() == 0) {
    15. return true;
    16. }
    17. return false;
    18. }
    19. };
    iterator erase (iterator p);

    其中,参数iterator是迭代器,即删除迭代器p指向的字符。返回值为删除后的字符串。

    哈希法 

    1. class Solution {
    2. public:
    3. bool canConstruct(string ransomNote, string magazine) {
    4. int record[26] = {0};
    5. //add
    6. if (ransomNote.size() > magazine.size()) {
    7. return false;
    8. }
    9. for (int i = 0; i < magazine.length(); i++) {
    10. // 通过record数据记录 magazine里各个字符出现次数
    11. record[magazine[i]-'a'] ++;
    12. }
    13. for (int j = 0; j < ransomNote.length(); j++) {
    14. // 遍历ransomNote,在record里对应的字符个数做--操作
    15. record[ransomNote[j]-'a']--;
    16. // 如果小于零说明ransomNote里出现的字符,magazine没有
    17. if(record[ransomNote[j]-'a'] < 0) {
    18. return false;
    19. }
    20. }
    21. return true;
    22. }
    23. };

    三、(leetcode 15)三数之和

    力扣题目链接

    状态:思路清楚,代码错误过多,照着正确版本修改后AC,注意去重的逻辑,i-1、i和i+1

    1. class Solution {
    2. public:
    3. vectorint>> threeSum(vector<int>& nums) {
    4. vectorint>> result;
    5. sort(nums.begin(), nums.end());
    6. // a = nums[i], b = nums[left], c = nums[right]
    7. for (int i = 0; i < nums.size(); i++) {
    8. // 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了
    9. if (nums[i] > 0) {
    10. return result;
    11. }
    12. if (i > 0 && nums[i] == nums[i - 1]) {
    13. continue;
    14. }
    15. int left = i + 1;
    16. int right = nums.size() - 1;
    17. while (right > left) {
    18. /*去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right<=left 了,从而漏掉了 0,0,0 这种三元组
    19. /*
    20. while (right > left && nums[right] == nums[right - 1]) right--;
    21. while (right > left && nums[left] == nums[left + 1]) left++;
    22. */
    23. while (right > left && nums[right] == nums[right - 1]) right--;
    24. while (right > left && nums[left] == nums[left + 1]) left++;
    25. */
    26. if (nums[i] + nums[left] + nums[right] > 0) right--;
    27. else if (nums[i] + nums[left] + nums[right] < 0) left++;
    28. else {
    29. result.push_back(vector<int>{nums[i], nums[left], nums[right]});
    30. // 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
    31. while (right > left && nums[right] == nums[right - 1]) right--;
    32. while (right > left && nums[left] == nums[left + 1]) left++;
    33. right--;
    34. left++;
    35. }
    36. }
    37. }
    38. return result;
    39. }
    40. };

    四、(leetcode 18)四数之和

    力扣题目链接

    状态:已AC,不过剪枝处理是什么,还需要查+回顾

    细节:

    不要判断nums[k]>target 就返回了,三数之和 可以通过nums[i]>0就返回了,因为 0 已经是确定的数了,四数之和这道题目 target是任意值。比如:数组是[-4,-3,-2,-1]target-10,不能因为-4 > -10而跳过

    1. class Solution {
    2. public:
    3. vectorint>> fourSum(vector<int>& nums, int target) {
    4. vectorint>> result;
    5. sort(nums.begin(), nums.end());
    6. for (int k = 0; k < nums.size(); k++) {
    7. // 剪枝处理
    8. if (nums[k] > target && nums[k] >= 0) {
    9. break;
    10. }
    11. if (k > 0 && nums[k] == nums[k - 1]) {
    12. continue;
    13. }
    14. for (int i = k + 1; i < nums.size(); i++) {
    15. // 2级剪枝处理
    16. if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) {
    17. break;
    18. }
    19. if (i > k + 1 && nums[i] == nums[i - 1]) {
    20. continue;
    21. }
    22. int left = i + 1;
    23. int right = nums.size() - 1;
    24. while (right > left) {
    25. // nums[k] + nums[i] + nums[left] + nums[right] > target 会溢出
    26. if ((long) nums[k] + nums[i] + nums[left] + nums[right] > target) {
    27. right--;
    28. // nums[k] + nums[i] + nums[left] + nums[right] < target 会溢出
    29. } else if ((long) nums[k] + nums[i] + nums[left] + nums[right] < target) {
    30. left++;
    31. } else {
    32. result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
    33. while (right > left && nums[right] == nums[right - 1]) right--;
    34. while (right > left && nums[left] == nums[left + 1]) left++;
    35. right--;
    36. left++;
    37. }
    38. }
    39. }
    40. }
    41. return result;
    42. }
    43. };

     

     

     

     

  • 相关阅读:
    基于php的中小型服装厂原料采购系统
    『现学现忘』Docker相关概念 — 2、云计算的服务模式
    C++初阶:C/C++内存管理
    如何用Python写一个简单的查询q绑程序(v1.0)
    使用Python绘制CPI和PPI曲线
    【Git】git的安装与使用教程
    因发表不当言论,开源作者遭 OBS 项目社区封杀
    沁恒微电子CH9120是一款网络串口透传芯片
    为你揭秘拼购为什么是破产老板手中的最后一根稻草?
    C. Yarik and Array Codeforces Round 909 (Div. 3) 1899C
  • 原文地址:https://blog.csdn.net/weixin_42179093/article/details/133317564