[leetcode] 15. 3Sum 解题报告

题目链接:https://leetcode.com/problems/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)

思路:刚开是的思路是排序+DFS搜索+回溯,时间复杂度是O(n^3),超时。

代码如下:

class Solution {
public:
    void DFS(vector<int>& nums, vector<int> tem, int index, int sum)
    {
        if(tem.size() == 3)//如果已经找到解,就不往下搜索了
        {
            if(sum == 0)
                result.push_back(tem);
            return;
        }
        if(index >= nums.size() || sum >0) return;
        tem.push_back(nums[index]);
        DFS(nums, tem, index+1, sum+nums[index]);
        while(index+1 < nums.size() && nums[index+1] == nums[index])//去除重复值
            index++;
        tem.pop_back();//回溯
        DFS(nums, tem, index+1, sum);
    }
    vector<vector<int>> threeSum(vector<int>& nums) {
        int len = nums.size();
        if(len ==0) return result;
        sort(nums.begin(), nums.end());
        vector<int> tem;
        DFS(nums, tem, 0, 0);
        return result;
    }
private:
    vector<vector<int>> result;
};

后来又看了一下别人的答案,发现可以这题可以退化成twoSum那题的解法。就是可以先挑出一个数来,然后在剩下的数里面找出两个数和这个数相加等于0.这样就把问题转换成了2Sum问题。

在挑出一个数作为target以后,会找出所有和这个数相关的解,因此,以后都可以不再搜索这个数了,不然会有重复解。

举个栗子:-10,-5,-5,5,5,6,10

第一次会挑选-10做为target,在-5,-5,5,5,6,10中搜索结果

第二次则挑选-5作为target,在-5,5,5,6,10挑选结果

第三次挑选5作为target,在5,6,10中挑选结果,这次跳过了一个-5,因为已经找过以-5为target的解了

恩!就这样,代码如下:

class Solution {
public:
    void twoSum(vector<int>& nums, int left, int target)
    {
        int right = nums.size() -1;
        while(left < right)
        {
            int value = nums[left] + nums[right] + target;
            if(value == 0)//找到了一个解
            {
                vector<int> tem;
                tem.push_back(target);
                tem.push_back(nums[left++]);
                tem.push_back(nums[right--]);
                result.push_back(tem);
                while(nums[left] == nums[left-1]) left++;//去重
                while(nums[right] == nums[right+1]) right--;//去重
            }
            else if(value < 0)
                left++;
            else if(value > 0)
                right--;
        }
    }
    vector<vector<int>> threeSum(vector<int>& nums) {
        int len = nums.size();
        if(len ==0) return result;
        sort(nums.begin(), nums.end());
        for(int i =0; i< len-1; i++)//枚举每一个值作为target
        {
            if(i >0 && nums[i] == nums[i-1])
                continue;
            twoSum(nums, i+1, nums[i]);
        }
        return result;
    }
private:
    vector<vector<int>> result;
};

第二种方法参考:http://www.sigmainfy.com/blog/summary-of-ksum-problems.html


2016-02-24再次编辑

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        if(nums.size() == 0) return result;
        sort(nums.begin(), nums.end());
        int len = nums.size();
        for(int i = 0; i< len -2; i++)
        {
            int left = i+1, right = len-1;
            while(left < right)
            {
                int val = nums[left] + nums[right] + nums[i];
                if(val ==0)
                {
                    result.push_back(vector<int>{nums[i], nums[left], nums[right]});
                    while(nums[left] == nums[left+1]) left++;
                    while(nums[right] == nums[right-1]) right--;
                    left++, right--;
                }
                else if(val > 0) right--;
                else left++;
            }
            while(i+1 < len && nums[i] == nums[i+1])
                i++;
        }
        return result;
    }
private:
    vector<vector<int>> result;
};








你可能感兴趣的:(LeetCode,算法,array)