day7_454四数相加II_383赎金信_15三数之和_18四数之和

文章介绍了力扣(LeetCode)上的几道编程题,包括四数相加II(454题)的解决方案,使用unordered_map存储两数之和及其出现次数,然后遍历另两个数组求解。此外,还讨论了赎金信(383题)的解题思路,通过哈希表检查字符是否足够构建ransomNote。15题三数之和的解答强调了排序和去重的复杂逻辑,以及在四数之和(18题)中要注意剪枝和防止溢出的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

454四数相加II

力扣题目链接

直接求救代码随想录

  1. 首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
  2. 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
  3. 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
//       1. 首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
//      2. 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
//      3. 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。  
    unordered_map<int, int> sum12;
    for(int i = 0; i < nums1.size(); i++){
        for(int j = 0; j < nums2.size(); j++){
            sum12[nums1[i] + nums2[j]]++;
        }
    }
    int result = 0;
    for(int k = 0; k < nums3.size(); k++){
        for(int l = 0; l < nums4.size(); l++){
            if(sum12.find(0-nums3[k]-nums4[l]) != sum12.end())
                result += sum12[0 - nums3[k] - nums4[l]];
        }
    }
    return result;
    }
};

383赎金信

力扣题目链接

42.有效的字母异位很像,思路一致。

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        // hash
        // string magazine ==》 set magazine
        // 遍历ransomNote,is in set magazine
        int record_magazine[26] = {0};
        for(int i = 0; i < magazine.size(); i++){
            record_magazine[magazine[i] - 'a'] += 1;
        }
        for(int j = 0; j < ransomNote.size(); j++){
            if(record_magazine[ransomNote[j] - 'a'] <= 0)
                return false;
            else{
                record_magazine[ransomNote[j] - 'a'] -= 1;
            }
        }
        return true;
        
    }
};

15三数之和

力扣题目链接

直接求助卡哥

  1. 先排序
  2. 去重逻辑很复杂,需要仔细看
    • 对于a的去重使用的是if continue,而不是while continue
    • b,c去重是在result.push_back之后进行去重的, 最后仍需left++, right–
class Solution
{
public:
    vector<vector<int>> threeSum(vector<int> &nums)
    {
        vector<vector<int>> results;
        // 先排序
        sort(nums.begin(), nums.end());
        // i遍历,nums[i] + nums[left]+ nums[right] == 0?
        for (int i = 0; i < nums.size(); i++)
        {
            if (nums[i] > 0)
                return results;
            else
            {
                // 去重a
                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) left += 1;
                    else if (nums[i] + nums[left] + nums[right] > 0)    right -= 1;
                    else{
                        results.push_back(vector<int>{nums[i], nums[left], nums[right]});
                        // b , c去重
                        while (left < right && nums[right] == nums[right - 1]) right--;
                        while (left < right && nums[left] == nums[left + 1]) left++;
                        right--;
                        left++;
                    }
                }
            }
        }
        return results;
    }
};

时间复杂度O(n的平方)

18四数之和

力扣题目链接

  1. 思路和上一题15三数之和类似,但是需要注意
  2. 不能简单判断nums[k] > target就剪枝,target可能是负数,数组是[-4, -3, -2, -1]target-10
  3. 计算四数之和可能会溢出,使用long转换一下
  4. 时间复杂度O(n的三次方)。
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        // nums[k] + nums[i] + nums[left] + nums[right] == target??
        vector<vector<int>> results;
        // 先排序
        sort(nums.begin(), nums.end());
        for(int k = 0; k < nums.size(); k++){
            // 剪枝
            if(nums[k] > target && nums[k] >= 0)
                break;
            // 去重a
            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;
                // 去重b
                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)    left++;
                    else if((long)nums[k] + nums[i] + nums[left] + nums[right] > target) right--;
                    else{
                        results.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
                        // 去重c, d
                        while(left < right && nums[left] == nums[left + 1]) left++;
                        while(left < right && nums[right] == nums[right - 1]) right--;
                        // 移动left, right
                        left++;
                        right--;
                    }
                }
            }
        }
        return results;
    }
};

TODO

  1. 15三数之和的 视频讲解:需要仔细看 去重逻辑

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值