zoukankan      html  css  js  c++  java
  • leetcode第15题--3Sum

    Problem:

    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)

    先说说我的思路吧。先排序。我也不知道为什么莫名其妙的想到固定中间一个数的方法。i从第二个开始一直到倒数第二个数,然后left从i的左边一个开始,right从i的右边一个开始,如果三个数相加大于零,那么肯定就要left往左,如果相加小于零那就right往右,如果等于零,再判断是否与已经存入sum中的最后一个判断比较不相等就写入。现在就碰到了以前没有碰到过的问题,不是Time Limit Exceeded,而是Output Limit Exceeded。查了下说,这个问题应该是while循环没有出来。但是我看了以下代码,没有理由没跳出来啊。
    class Solution {
    public:
    vector<vector<int> > threeSum(vector<int> &num)
    {
        bool flag = false;
        vector<vector<int> > sum;
        vector<int> temp = num;
        sort(temp.begin(), temp.end());
        if (num.size() < 3 || temp[0] > 0)
        return sum;
        
        for (int i = 1; i != num.size() - 1; i++)
        {
            int left = i - 1, right = i + 1;
            while(left>=0 && right < num.size())
            {
                if (temp[left] + temp[i] + temp[right] == 0)
                {
                    vector<int> sub;
                    sub.push_back(temp[left]);
                    sub.push_back(temp[i]);
                    sub.push_back(temp[right]);
                    if (!flag)
                    {
                        flag = true;
                        sum.push_back(sub);
                    }
                    else if(sub != sum[sum.size()-1])
                    {
                        sum.push_back(sub);
                    }
                    left--;
                    right++;
                }
                else if(temp[left] + temp[i] + temp[right] < 0)
                {
                    right++;
                }
                else
                    left--;
            }
        }
        sum.erase(unique(sum.begin(), sum.end()), sum.end());
        return sum;
    }
    };

    后来请实验室的大牛(可能要去Google工作了)看了下。说应该是内存不够了。就是还是存了相同的例子。单单用判断是不是等于sum的最后一个是否相等是不行的。应该是这样,OJ里测试的时候估计给了sum的大小有限。如果重复了那就Output Limit了。其实我差成功只是一小步了。

    以下代码是固定三个数的第一个,然后i从第一个到倒数第三个就行了。如果i往前移动的时候和前一个数相等那就不用再判断了,直接i++,因为以该数开头的三元组都已经计算过并存起来了。其中还有一个很好的地方就是在判断三元组是不是第一个的时候,用的是sum.size()==0 || sum.size() > 0 ...这个很好,因为第一次的时候是==0的,那||之后的就不作判断了。下一次的时候size不==0.再做后面的判断,后面的判断是因为三个数只要有两个数相等那第三个肯定也相等。代码如下。

    class Solution {
    public:
        vector<vector<int> > threeSum(vector<int> &num) {
            vector<vector<int> > sum;
            if(num.size()<3)
                return sum;
            sort(num.begin(),num.end());
            int k = 0;
            for(int i = 0;i<num.size()-2;i++)
            {
                if(i>0 && num[i] == num[i-1])
                    continue;
                int j = i+1;
     
                if(num[i]+num[j]>0)
                    break;
                k = num.size()-1;
                while(j<k)
                {
                if(num[i]+num[j]+num[k] == 0)
                {
                    if(sum.size()==0 || sum.size()>0 && !(num[i]==sum[sum.size()-1][0]&& num[j] ==sum[sum.size()-1][1] ))
                    {
                    vector<int> ansPiece;
                    ansPiece.push_back(num[i]);
                    ansPiece.push_back(num[j]);
                    ansPiece.push_back(num[k]);
                    sum.push_back(ansPiece);
                    }
                }
                if(num[i]+num[j]+num[k] < 0)
                    j++;
                else
                    k--;
                }
            }
            return sum;
        }
    };

    2015/4/3:

    class Solution {
    public:
        vector<vector<int> > threeSum(vector<int> &num) {
            sort(num.begin(), num.end());
            vector<vector<int> > ans;
            for (int i = 0; i < num.size(); i++){
                int target = -1 * num[i];
                if (i > 0 && num[i] == num[i-1])
                    continue;
                int left = i + 1, right = num.size() - 1;
                while (left < right){
                    if (target == num[left] + num[right]){
                        vector<int> tmp;
                        tmp.push_back(num[i]);
                        tmp.push_back(num[left]);
                        tmp.push_back(num[right]);
                        ans.push_back(tmp);
                        while(left < num.size() && num[left] == tmp[1])
                            left++;
                        while(right > 0 && num[right] == tmp[2])
                            right--;
                    }
                    else if (target > num[left] + num[right])
                        left++;
                    else
                        right--;
                }
                
            }
            return ans;
        }
    };
  • 相关阅读:
    idea 没有 persistence
    java 枚举(二) 级联关系
    java to edi 动态/静态映射
    edi to java
    C# 扩展方法
    最详细的C++对应C#的数据类型转换
    c# .Net随机生成字符串代码
    遍历结构体内部元素和值(Name and Value)
    寒假学习计划
    python os.path模块
  • 原文地址:https://www.cnblogs.com/higerzhang/p/4029891.html
Copyright © 2011-2022 走看看