LeetCode(18)4Sum

来源:互联网 发布:gta5画面设置优化 编辑:程序博客网 时间:2024/06/10 16:27

题目

Given an array S of n integers, are there elements a, b, c, 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)

分析

类似于15题求解的3Sum问题,这次求解4Sum问题,本质是相同的,不可以采用穷举法;
其实求解4Sum问题可以分解为求3Sum问题,对数列依次遍历i,我们只需得到在第i个数后面,找出所有和为targetnums[i]的三元组,同理求3Sum又可以退化为2Sum,进而退化为1Sum
因此,采用递归的思想解决KSum问题 ,但是递归的性能总是不满意的 , 意料之中的TLE。

转换思路,我们可以使用2-sum的变形,两层遍历首先确定前两个元素,在确定后两个元素时采用2-sum的方式解决;

学习:关于2-sum 3-sum 和 4-sum 乃至于k-sum问题一个很好的总结。

AC代码

class Solution {public:    /*4-sum算法,递归实现,TLE*/    vector<vector<int>> fourSum1(vector<int>& nums, int target) {        if (nums.empty())            return vector<vector<int>>();        sort(nums.begin(), nums.end());        return k_Sum(nums, 0, 4, target);    }    /*k-sum算法*/    vector<vector<int>> k_Sum(vector<int> &nums, int begPos, int count, int target)    {        if (nums.empty())            return vector<vector<int>>();        /*所输入序列为已排序*/        int len = nums.size();        unordered_set<int> visited;        vector<vector<int>> ret;        vector<int> tmp;        /*2-sum 处理*/        if (2 == count)        {            int i = begPos, j = len - 1;            while (i < j)            {                int sum = nums[i] + nums[j];                if (sum == target && visited.find(nums[i]) == visited.end())                {                    tmp.clear();                    tmp.push_back(nums[i]);                    tmp.push_back(nums[j]);                    ret.push_back(tmp);                    /*加入已访问set*/                    visited.insert(nums[i]);                    visited.insert(nums[j]);                    ++i;                    --j;                }//if                else if (sum < target)                    ++i;                else                    --j;            }//while        }//if        else{            for (int i = begPos; i < len; ++i)            {                if (visited.find(nums[i]) == visited.end())                {                    visited.insert(nums[i]);                    /*得到k-1 sum的序列*/                    vector<vector<int>> subRet = k_Sum(nums, i+1, count - 1, target-nums[i]);                    if (!subRet.empty())                    {                        int sz = subRet.size();                        for (int j = 0; j < sz; ++j)                        {                            subRet[j].insert(subRet[j].begin(), nums[i]);                        }//for                        ret.insert(ret.end(), subRet.begin(), subRet.end());                    }//if                }//if            }//for        }//else        /*返回结果集*/        return ret;    }    /*4-sum算法,方法二,2-sum的变形*/    vector<vector<int>> fourSum(vector<int>& nums, int target) {        if (nums.empty() || nums.size() < 4)            return vector<vector<int>>();        sort(nums.begin(), nums.end());        int len = nums.size();        set<vector<int>> tmpRet;        vector<vector<int>> res;        for (int i = 0; i < len; ++i)        {            for (int j = i + 1; j < len; ++j)            {                int beg = j + 1, end = len - 1;                while (beg < end)                {                    int sum = nums[i] + nums[j] + nums[beg] + nums[end];                    if (sum == target)                    {                        vector<int> tmp = { nums[i], nums[j], nums[beg], nums[end] };                        tmpRet.insert(tmp);                        ++beg;                        --end;                    }                    else if (sum < target)                    {                        ++beg;                    }                    else                        --end;                }//while            }//for                  }//for        auto iter = tmpRet.begin();        while (iter != tmpRet.end())        {            res.push_back(*iter);            ++iter;        }//while        return res;    }};

GitHub测试程序源码

0 0