[LeetCode] 15 3Sum

原题地址:

https://leetcode.com/problems/3sum/description/

题目:

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: 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]
]

解法:

这道题是2Sum的“进化版”,一开始我采用回溯法去解决,显然这是个极其不适合这道题目的方法,结果也如同猜测一样:TLE。这也给了我一个做这类题目的启发:当确定了结果中数组元素的个数时(特别是2个、3个这种),是肯定不会采用回溯法解决的。像Combination Sum那一类题目,结果中数组元素不确定时,才有可能使用回溯法。

既然是2Sum的进化版,我们就可以采用类似的办法去解决。我们可以先确定一个元素,然后再遍历剩下的元素,只要剩下的元素中有两个元素的和是我们确定元素的相反数时,这三个元素就是其中一个结果了。2Sum的时间复杂度为O(n),我们再在外面加一层循环,时间复杂度为O(n2),可以接受。下面是代码:

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

下面是代码中的一些细节:

(1)首先要排序,然后最外的循环只需要循环到<=0的部分就可以了;

(2)为了避免出现重复,要加入

if (nums[k] == nums[k - 1] && k > 0) continue;

这个语句,比如[-4, -1, -1, 0, 1, 2]这个样例,假如不加这个语句,会出现两个[-1,0,1].

(3)下面这两个语句:

while (i < j && nums[i + 1] == nums[i]) i++;
while (i < j && nums[j - 1] == nums[j]) j--;

想一下这个样例:[-2,0,0,2,2]

假如不加这两个语句,结果会有两个[-2,0,2]:因为最外一层循环为-2时,i=1,j=4和i=2,j=3都符合条件,而两者会出现重复,因此要忽略等于前一个元素值的元素。

总结一下(2)(3)这两点,可以发现这道题目会出现两种重复的原因,各自有不同的解决方法,这也是这道题困难的地方。

相关题目:

Two Sum:http://www.cnblogs.com/fengziwei/p/7501933.html

原文地址:https://www.cnblogs.com/fengziwei/p/7827719.html