4Sum

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

Note:

  • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
  • The solution set must not contain duplicate quadruplets.

    For example, given array S = {1 0 -1 0 -2 2}, and target = 0.

    A solution set is:
    (-1,  0, 0, 1)
    (-2, -1, 1, 2)
    (-2,  0, 0, 2)

注意该问题的答案中,每个quadruplet内部可以有重复的数字,但quadruplet之间不能重复。即每个quadruplet内四个元素对应的index不能重复。本文给出两种解法。

解法一,先排序,然后用一个hashmap记录每两两个数的和和这两个数对应的index(注意是index而不能仅仅记录这两个数,防止重复)。时间复杂度,平均O(n^2),最坏O(n^4),空间O(n^2)。最后对结果sort并去重。代码如下。

class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        vector<vector<int> > result;
        const int len = num.size();
        if(len < 4) return result;
        sort(num.begin(), num.end());
        
        unordered_map<int, vector<pair<int, int> > > cache;
        
        for(int i=0; i<len; i++)
            for(int j=i+1; j<len; j++)
                cache[num[i]+num[j]].push_back(pair<int,int>(i, j));
        
        for(int i=0; i<len; ++i) {
            for(int j=i+1; j<len; ++j) {
                int left = target-num[i]-num[j];
                if(cache.find(left) == cache.end()) continue;
                
                vector<pair<int,int> > t = cache[left];
                for(int k=0; k<t.size(); ++k)
                {
                    if(i <= t[k].second)
                        continue;
                    result.push_back({num[t[k].first], num[t[k].second], num[i], num[j]});
                }
            }
        }
        sort(result.begin(), result.end());
        result.erase(unique(result.begin(), result.end()), result.end());
        return result;
    }
};

解法二,仍然使用hash, 时间O(n^2), 空间O(n^2)。先缓存没两个数的和,然后遍历hash,根据sum2在常数时间内找出另一个sum2,然后遍历两个sum2对应的list,根据其pair组成四元组。代码如下所示。

class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        vector<vector<int> > result;
        const int len = num.size();
        if(len < 4) return result;
        sort(num.begin(), num.end());
        
        unordered_map<int, vector<pair<int, int> > > cache;
        
        for(int i=0; i<len; i++)
            for(int j=i+1; j<len; j++)
                cache[num[i]+num[j]].push_back(pair<int,int>(i, j));
        
        unordered_map<int, vector<pair<int, int> > >::iterator it = cache.begin();
        for(; it != cache.end(); ++it)
        {
            int left = target-it->first;
            if(cache.find(left) == cache.end()) continue;
            
            vector<pair<int, int> > v1 = it->second;
            vector<pair<int, int> > v2 = cache[left];
    
            for(int i=0; i<v1.size(); ++i)
                for(int j=0; j<v2.size(); ++j)
                {
                    auto a = v1[i].first;
                    auto b = v1[i].second;
                    auto c = v2[j].first;
                    auto d = v2[j].second;
                    if(b < c)
                        result.push_back({num[a], num[b], num[c], num[d]});
                }
        }
        
        sort(result.begin(), result.end());
        result.erase(unique(result.begin(), result.end()), result.end());
        return result;
    }
};

参考求和问题总结(leetcode 2Sum, 3Sum, 4Sum, K Sum)):http://tech-wonderland.net/blog/summary-of-ksum-problems.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值