LeetCode —— 3SUM

3Sum

链接:http://leetcode.com/onlinejudge#question_15

原题:

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

Note:

  • Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ? b ? c)
  • The solution set must not contain duplicate triplets.

    For example, given array S = {-1 0 1 2 -1 -4},

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

思路:DFS + 剪枝

暴力搜索,复杂度是O(n^3),可以加剪枝

先对数组排序

1)如果 sum + array[i] > 0 那么就不用递归下去了

2)如果 i > start, 并且 array[i] == array[i-1],就不用递归了,这样还可以避免重复到组合进入最终结果里


做完之后,搜了一下其他人到做法,发现有O(n^2)到算法,还是蛮巧妙到,大概到思路是

先排序,然后对第一个数进行0到size-3遍历,后两个数是两头往中间走。具体可以参考:

http://www.cnblogs.com/etcow/articles/2547108.html


代码:

class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<int> vec;
        vector<vector<int> > collection;
        sort(num.begin(), num.end(), less<int>() );
        search(0, 0, 3, num, vec, collection);
        
        return collection;
    }
    
private:
    void search(int start, int sum, int count, 
        const vector<int> &array, vector<int> &vec, vector<vector<int> > &collection) {
        
        if (count == 0) {
            if (sum == 0)
                collection.push_back(vec);
            return;
        }
        
        int size = array.size() - count;
        for (int i=start; i<=size; i++) {
            if (i > start && array[i-1] == array[i])
                continue;
            if (sum + array[i] > 0)
                return;
            vec.push_back(array[i]);
            search(i+1, sum+array[i], count-1, array, vec, collection);
            vec.pop_back();
        }
    }
};

3Sum Closest

链接:http://leetcode.com/onlinejudge#question_16

原题:

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

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

    The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

思路:如果将三个数的和减去target,那么就是求最接近0到组合了,就可以归结为3sum的问题了。

这回尝试用遍历第一个数,然后后两个数从两端往中间走的策略。复杂度为O(n^2),当然先排序。

代码:

class Solution {
public:
    int threeSumClosest(vector<int> &num, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if (num.size() <= 3) {
            int sum = 0;
            for (int i=0; i<num.size(); i++)
                sum += num[i];
            return sum;
        }
        
        int min = num[0] + num[1] + num[2] - target;
        sort(num.begin(), num.end(), less<int>() );
        for (int i=0; i<num.size()-2; i++) {
            if (i>0 && num[i] == num[i-1])
                continue;
            int part = num[i] - target;
            for (int m=i+1, n=num.size()-1; m<n; ) {
                int sum = part + num[m] + num[n];
                if (abs(sum) < abs(min))
                    min = sum;
                if (sum > 0)
                    n--;
                else if (sum < 0)
                    m++;
                else
                    return target;
            }
        }
        
        return target + min;
    }
};

4Sum

链接:http://leetcode.com/onlinejudge#question_18

原题:

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)

思路:直接用 DFS + 剪枝会超时,所以采用一二两个数遍历,三四两个数两头向中间靠拢,

要小心重复组合的加入。

代码:

class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<int> vec;
        vector<vector<int> > collection;
        if (num.size() < 4)
            return collection;
        sort(num.begin(), num.end(), less<int>() );
        search(0, 0, 4, target, num, vec, collection);
        
        return collection;
    }

private:
    void search(int start, int sum, int count, int target,
        const vector<int> &array, vector<int> &vec, vector<vector<int> > &collection) {
          
        if (count == 2) {
            for (int m=start, n=array.size()-1; m<n;) {
                int temp = sum + array[m] + array[n];
                if (temp < target)
                    m++;
                else if (temp > target)
                    n--;
                else {
                    vec.push_back(array[m]);
                    vec.push_back(array[n]);
                    collection.push_back(vec);
                    vec.pop_back();
                    vec.pop_back();
                    m++; n--;
                    while (m < array.size() && array[m] == array[m-1]) m++;
                    while (n >= 0 && array[n] == array[n+1]) n--;
                }
            }
            return;
        }
         
        int size = array.size() - count;
        for (int i=start; i<=size; i++) {
            if (i > start && array[i-1] == array[i])
                continue;
            vec.push_back(array[i]);
            search(i+1, sum+array[i], count-1, target, array, vec, collection);
            vec.pop_back();
        }
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值