每天算法之十四:3Sum

每日算法之十四: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:18px;"> class Solution {
   
 public: vector<vector<int>> threeSum(vector<int> &num) {

        vector<vector<int> > v;
        if(num.size()<3)//不足以构成三元组
            return v;
        sort(num.begin(),num.end());
        for(vector<int>::size_type i = 0;i<num.size()-2;i++)
        {
            if(num[i]>0) break;//首元素大于零,那么三个元素求和肯定大于零,不满足条件。序列是有序的
            int j = i+1,k = num.size()-1;
            while(j<k)
            {
                if (num[i] + num[j] > 0)  //同上
                    break;  
                if (num[j] + num[k] < -num[i])  
                    ++j;  
                else if (num[j] + num[k] > -num[i])  
                    --k; 
                else
                {
                    vector<int> temp;
                    temp.push_back(num[i]);
                    temp.push_back(num[j]);
                    temp.push_back(num[k]);
                    v.push_back(temp);
                    while(j<k&&num[j] == num[j+1]) j++;//这都是要去重
                    while(k>j&&num[k] == num[k-1]) k--;
                    j++;
                    k--;
                }
                while(i<num.size()-2&&num[i] == num[i+1]) ++i;//三个指针都需要去重
            }
        }
        return v;
 }
};</span>