3Sum 分类: Leetcode(线性表) 2015-02-04 10:51 51人阅读 评论(0) 收藏

3Sum


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)


暴力破解失败

<span style="font-size:10px;">class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        vector<vector<int>> result;
        if (num.size() <3) return result;
        vector<int> vec;
        sort(num.begin(), num.end());
        const int target = 0;
        
        int i,j,k;
        for(i = 0; i < num.size(); i++){
            for(j = num.size()-1; j > i; j--){
                for(k = i; k < j; k++){
                    if(num[i]+num[k]+num[j] == 0){
                        vec.push_back(num[i]);
                        vec.push_back(num[k]);
                        vec.push_back(num[j]);
                        result.push_back(vec);
                    }
                }
            }
        }
        return result;
    }
};</span>


下来考虑夹击,还需要注意题目的要求,不能三个数都相同
class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
        vector<vector<int>> result;
        if (num.size() <3) return result;
        vector<int> vec;
        sort(num.begin(), num.end());
        const int target = 0;
        
        int i,j,k;
        int last = num.size();
        for(i = 0; i < num.size(); i++){
            j = i+1;
            if( i > 0 && num[i] == num[i-1]) continue;
            k = num.size()-1;
            while(j < k){
                if( num[i] + num[j] + num[k] < target){
                    ++j;
                    while( num[j] == num[j-1] && j < k) ++j;
                } else if( num[i] + num[j] + num[k] > target){
                    --k;
                    while( num[k] == num[k+1] && j<k) --k; 
                } else{
                    result.push_back( {num[i],num[j], num[k]});
                    ++j;
                    --k;
                    while( num[j] == num[j-1] && num[k] == num[k+1] && j < k) ++j;
                }
            }
        }
        return result;
    }
};

我们看到循环中j=i+1是在跳过相同数的前面的,这是因为两个数相同时可以的。i和k分别指向数组的起始和终止位置,循环中有i 和 j=i+1,然后i跳过所有相同的数,接下来考虑三个数的和,如果和小于目标函数,那么说明j取小了,我们移动j,如果和大于目标函数,说明k取大了,我们移动k.我们可以看到,其实只有二重循环,i的循环,对于每个i,在n-i的长度里移动j和k,所以这样时间复杂度就降为了O(n^2),时间复杂度降低的关键是算法一的k这层的循环在算法二中没有了。

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

原文地址:https://www.cnblogs.com/learnordie/p/4656957.html