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

一、454.四数相加II

本题只需要写出满足要求的组数,故较为简单:

若改为要求返回 i, j, k, l 的值,则代码为:

vector<vector<int>> fourSumUniqueValues(vector<int>& nums1, vector<int>& nums2,
                                        vector<int>& nums3, vector<int>& nums4) {
    unordered_map<int, vector<pair<int, int>>> sumMap;
    set<vector<int>> uniqueTuples;

    // 构建 nums1 与 nums2 的所有和值及其索引
    for (int i = 0; i < nums1.size(); ++i) {
        for (int j = 0; j < nums2.size(); ++j) {
            int sum = nums1[i] + nums2[j];
            sumMap[sum].emplace_back(i, j);
        }
    }

    // 遍历 nums3 和 nums4,看是否存在可配对的 target
    for (int k = 0; k < nums3.size(); ++k) {
        for (int l = 0; l < nums4.size(); ++l) {
            int target = -(nums3[k] + nums4[l]);
            if (sumMap.count(target)) {
                for (auto& [i, j] : sumMap[target]) {
                    vector<int> quad = {nums1[i], nums2[j], nums3[k], nums4[l]};
                    sort(quad.begin(), quad.end()); // 排序后去重
                    uniqueTuples.insert(quad);
                }
            }
        }
    }

    // 将结果转为 vector<vector<int>>
    return vector<vector<int>>(uniqueTuples.begin(), uniqueTuples.end());
}

此处需要记录i, j, k, l,故需要创建一个map:

其中,sum作为key键,[i, j]作为value来储存结果。

二、383. 赎金信

注意点:比较数组和字符串在迭代器写法中的差异。

三、15. 三数之和

 本题难点在于去重。

开始思路想过创建一个set来为数组中的元素去重,但是之后思考并不满足题意:

即存在(1,1,-2)这样的三元组满足题意,但是如用set去重则会将这个答案也删去,故不行。

结果代码如下:

其中,值得注意是剪枝操作:
1处为:排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果。

2处 i>1的限制条件,一为防止i-1越界访问,二为了防止漏掉-1,-1,2 这种情况。

3处 while循环中left < right的限制条件:

起初想的是外部的大while循环会限制 left < right,但是内部会优先越界访问造成无限循环,故需要在内部添加限制条件。

四、18. 四数之和

思路同上,主要是几个注意点:

这题不能提前返回res,可能后续会有符合结果的组合,故使用break在代码结尾统一返回。

long定义sum来防止int上下限溢出,sum需要定义在while( left < right)内部,来保证sum每次循环重新计算。

 以及break的一重剪枝需要和三数之和做区分:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值