57 三数之和

原题网址:https://www.lintcode.com/problem/3sum/description

描述

给出一个有n个整数的数组S,在S中找到三个整数a, b, c,找到所有使得a + b + c = 0的三元组。

在三元组(a, b, c),要求a <= b <= c。

结果不能包含重复的三元组。

您在真实的面试中是否遇到过这个题?  

样例

如S = {-1 0 1 2 -1 -4}, 你需要返回的三元组集合的是:

(-1, 0, 1)

(-1, -1, 2)

 

标签

 

排序
两根指针
数组
 
思路:
不考虑时间复杂度、空间复杂度的话,三重循环暴力破解,唉,菜鸟第一想法。找到一组答案后判断下是否与result中已有组合重复,这个判重可以单独定义成一个函数。
 
AC代码:
class Solution {
public:
    /**
     * @param numbers: Give an array numbers of n integer
     * @return: Find all unique triplets in the array which gives the sum of zero.
     */
    vector<vector<int>> threeSum(vector<int> &numbers) {
        // write your code here
        vector<vector<int>> result;
    int size=numbers.size();
    for (int i=0;i<size;i++)
    {
        for (int j=i+1;j<size;j++)
        {
            for (int k=j+1;k<size;k++)
            {
                if (numbers[i]+numbers[j]+numbers[k]==0)
                {
                    vector<int> temp;
                    temp.push_back(numbers[i]);
                    temp.push_back(numbers[j]);
                    temp.push_back(numbers[k]);
                    sort(temp.begin(),temp.end());
                    if (result.empty())
                    {
                        result.push_back(temp);
                    }
                    else
                    {
                        bool canInsert=true;
                        for (int ind=0;ind<(int)result.size();ind++)
                        {
                            if(same(temp,result[ind]))
                            {
                                canInsert=false;
                                break;
                            }
                        }
                        if (canInsert)
                        {
                            result.push_back(temp);
                        }
                    }
                }
            }
        }
    }
    return result;
    }
    
    
    bool same(vector<int> num1,vector<int> num2)
{
    for (int i=0;i<(int)num1.size();i++)
    {
        if (num1[i]!=num2[i])
        {
            return false;
        }
    }
    return true;
}

};

 

最开始我也是顺着两数之和的思路,先固定一个索引,另外两个数用哈希表,但会造成重复问题,并且会漏检一些组合,比如有多种组合nums【j】+ nums【k】= target的情况,只能检测出一种。
网上看了别人的答案后醍醐灌顶,膜拜大神。
详细见上面链接,简单说来就是先排序,然后固定一个数i,再用两个指针一根从头(i+1)一根从尾(n-1)遍历余下的元素,如果三个数的和等于0,push到结果中。如果和大于0,尾指针前移(减小总体和)。反之如果和小于0,头指针后移(增大总体和)。
这里尤其注意去除重复,因为数组已经排过序,只需要判断i,j,k三根指针是否与上一个指向元素相同就可以了。
代码,Lintcode说我 Time Limit Exceeded,emmmm……暴力破解反而通过?费解
class Solution {
public:
    /**
     * @param numbers: Give an array numbers of n integer
     * @return: Find all unique triplets in the array which gives the sum of zero.
     */
    vector<vector<int>> threeSum(vector<int> &numbers) {
        // write your code here
        vector<vector<int>> result;
    int n=numbers.size();
    sort(numbers.begin(),numbers.end());
    for (int i=0;i<n;i++)
    {
        if (numbers[i]>0)
        {
            break;
        }
        if (i>0&&numbers[i]==numbers[i-1])//去除重复;
        {
            continue;
        }
        int j=i+1,k=n-1;
        while(j<k)
        {
            if (j>i+1&&numbers[j-1]==numbers[j])//去除重复;
            {
                continue;
            }
            if (k<n-1&&numbers[k]==numbers[k+1])//去除重复;
            {
                continue;
            }
            if (numbers[i]+numbers[j]+numbers[k]==0)
            {
                vector<int> tmp(3,numbers[i]);
                tmp[1]=numbers[j];
                tmp[2]=numbers[k];
                result.push_back(tmp);
                j++;
                k--;
            }
            else if (numbers[i]+numbers[j]+numbers[k]>0)
            {
                k--;
            }
            else
            {
                j++;
            }
        }
    }
    return result;
        
    }
};

 

posted @ 2018-05-30 15:44  eeeeeeee鹅  阅读(210)  评论(0编辑  收藏  举报