Leetcode-18: 4Sum

本文介绍了一种解决4Sum问题的方法,即寻找数组中四个数的组合使其总和等于目标值,同时确保解决方案集不含重复的四元组。文中提供了两种解决方案:一种是通过两层循环配合双指针技术实现,时间复杂度为O(n^3);另一种是将数组中的元素两两相加形成新数组再使用2Sum方法解决,时间复杂度为O(n^2)。

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

  1. 4Sum
    Medium

Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Notice that the solution set must not contain duplicate quadruplets.

Example 1:

Input: nums = [1,0,-1,0,-2,2], target = 0
Output: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
Example 2:

Input: nums = [], target = 0
Output: []

Constraints:

0 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109

解法1:跟3Sum差不多。时间复杂度O(n^3),因为3sum时间复杂度是O(n ^2), 2sum时间复杂度是O(n)。
代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;

vector<vector<int>> fourSum(vector<int>& nums, int target) {
    vector<vector<int>> vv;
    if (nums.size()<4) return vv;

    sort(nums.begin(), nums.end());

    set<vector<int> > s;

    for (int i=0; i<nums.size()-3; ++i) {
        for (int j=i+1; j<nums.size()-2; ++j) {
            int diff2 = target-nums[i]-nums[j];
            int p1=j+1, p2=nums.size()-1;
            while(p1<p2) {
                int sum = nums[p1]+nums[p2];
                if (sum<diff2) p1++;
                else if (sum>diff2) p2--;
                else {
                     s.insert(vector<int>{nums[i], nums[j], nums[p1], nums[p2]});
                     p1++; p2--;   //do not directly break as there may be some other solutions left.
                }
            }
        }
    }

    for (auto it=s.begin(); it!=s.end(); ++it)   //note: should not use it<s.end() as set does not provide operator<
        vv.push_back(*it);

    return vv;
}

int main()
{
    //vector<int> S={1, 0, -1, 0, -2, 2};
    vector<int> S={-3,-2,-1,0,0,1,2,3};
    vector<vector<int> > vv;

    vv=fourSum(S, 0);

    cout<<"["<<endl;
    for (auto i : vv) {
        cout<<" [ ";
        for (auto j : i) cout<<j<<" ";
        cout<<"],"<<endl;
    }
    cout<<"]"<<endl;
    return 0;
}

要注意的地方有:

  1. 当找到一个解后,不要直接退出,还要p1++,p2–。因为可能还有其他解。
  2. set的iterator不支持operator<,只能用!=。这可能跟set内部是用RB tree有关,没法用<来判断。

解法2:把nums的元素两两相加,并记录(sum, pair(i, j)),这样就可以构成一个长度为n2n^2n2的数组,然后就可以直接用2sum了。时间复杂度是O(n2)O(n^2)O(n2)。下次做。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值