1. 题目

Given an array S of n integers, are there elements a, b, c 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]
]

2. 思路

先建立hash表,然后两层遍历,查找第三个余数是否存在。余数直接用sum减去前两个的和。
先做好排序,nlogn比n^2小很多,多做一次不影响。
遍历时,如果发现要求的第三个数已经比第二个数小,就可以跳过后续了,因为不可能找到了。即由于有序,这三个数是在排序后的数组有序且递增的。
如果第一个数就大于0,则整体肯定大于0,可以全部跳过后续。
考虑做去重,由于有序,在同一个第一个数下,当前的第二个数如果等于上一次的第二个数,则整体一定相同,可以跳过。

3. 代码

耗时:55ms

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int> > ret;
        if (nums.size() == 0) return ret;
        sort(nums.begin(), nums.end());
        std::unordered_map<int,int> map;
        for (int i = 0; i < nums.size(); i++) {
            map[nums[i]] = i;
        }

        for (int i = 0; i < nums.size() - 2; i++) {
            if (nums[i] > 0) return ret;
            if (i>0 && nums[i] == nums[i-1]) continue;
            for (int j = i+1; j < nums.size() - 1; j++) {
                if (j-1>i && nums[j]==nums[j-1]) continue;
                int two = nums[i] + nums[j];
                if (-two < nums[j]) break;
                if (two > 0) return ret;
                auto it = map.find(-two);
                if (it!= map.end() && it->second > j) {
                    vector<int> r;
                    r.push_back(nums[i]);
                    r.push_back(nums[j]);
                    r.push_back(-two);
                    ret.push_back(r);
                }
            }
        }
        return ret;
    }
};

knzeus
72 声望28 粉丝

行万里路,读万卷书