【3Sum】cpp

题目

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)

代码

class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
            std::vector<std::vector<int> > ret_vector;
            if (num.size() < 3)
            {
                return ret_vector;
            }
            // sort the vector
            std::sort(num.begin(), num.end());
            // visit all the left side element of the current element
            const int target = 0;
            std::vector<int>::iterator end = num.end();
            for (std::vector<int>::iterator i = num.begin(); i != end-2; ++i){
                // ignore first duplicate i
                if ( i > num.begin() && *i==*(i-1)) continue;
                std::vector<int>::iterator j = i+1;
                std::vector<int>::iterator k = end-1;
                while (j<k){
                    const int tmp = *i+*j+*k;
                    if ( tmp < target ){
                        ++j;
                        while ( *j==*(j-1) && j<k ) ++j;
                    }
                    else if ( tmp > target ){
                        --k;
                        while ( *k==*(k+1) && j<k ) --k;
                    }
                    else{
                        int tmp_triple[3] = {*i,*j,*k};
                        std::vector<int> tmp_vector(tmp_triple,tmp_triple+3);
                        ret_vector.push_back(tmp_vector);
                        ++j;
                        --k;
                        while( *j==*(j-1) && *k==*(k+1) && j<k ) {
                            ++j;
                            --k;
                        }
                    }
                }
            }
            return ret_vector;
    }
};

Tips:

1. 先对传入的vector排序,然后从前向后遍历。原则是:包含*i元素,且满足条件的triple都加入到返回结果中

2. 这里比较困难的一点是排除重复的triple,大概想一想原则,一些极端的case只能试验出来了

另,在mac上编辑的,不知道为什么用数组初始化vector编译不通过,所以采用了比较麻烦的传参方式

===============================================

第二次过这道题,大体思路记得不太清,重新学习了一下“排序+双指针夹逼”方法

参考的blog:http://www.cnblogs.com/tenosdoit/p/3649607.html

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
            vector<vector<int> > ret;
            if ( nums.size()<3 ) return ret;
            std::sort(nums.begin(), nums.end());
            for ( int i=0; i<nums.size()-2; ++i )
            {
                // skip the duplicates elements
                if ( i>0 && nums[i]==nums[i-1] ) continue;  
                Solution::TwoSum(ret, nums, i+1, 0-nums[i]);
            }
            return ret;
    }
    static void TwoSum(vector<vector<int> >& ret, vector<int>& nums, int begin, int target)
    {
            vector<int> tmp;
            int start = begin;
            int end = nums.size()-1;
            while ( begin<end )
            {
                if ( nums[begin]+nums[end]<target ){
                    begin++;
                }
                else if ( nums[begin]+nums[end]>target ){
                    end--;
                }
                else
                {
                    // add a triple
                    tmp.push_back(nums[start-1]);
                    tmp.push_back(nums[begin]);
                    tmp.push_back(nums[end]);
                    ret.push_back(tmp);
                    tmp.clear();
                    // skip the duplicate elements
                    begin++;
                    while ( begin<end && nums[begin]==nums[begin-1] ) begin++;
                    end--;
                    while ( begin<end && nums[end]==nums[end+1] ) end--;
                }
            }
    }
};

tips:

1. 先对数组进行排序

2. 固定一个元素,从其后面元素开始,采用两头夹逼的方式进行遍历。(为什么要两边夹逼?因为元素已经从小到大排序好了,向后移动begin可以增加两个元素的和,向前移动end可以减小两个元素的和;采用这样的方式,相当于进可往最大和靠,退可往最小值收,可以保证不漏)

3. 如果遇到重复的元素要跳过去,因为题中要求不能出现重复的triple。

原文地址:https://www.cnblogs.com/xbf9xbf/p/4439240.html