3Sum--LeetCode

来源:互联网 发布:卸载加密软件 编辑:程序博客网 时间:2024/06/07 07:08

1.题目

3Sum

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.题意

在数组中找到和为0的三个数,结果不重复

3.分析

本题是Two Sum的扩展,brute force时间复杂度为O(n^3)
但这里使用哈希表的解法并不合适,因为结果数组中的元素可能出现重复
因此应该先排序,然后左右夹逼
用0减去[0,nums.size()-2)中的一个数得到一个sum
在剩余子数组中找到两数之和等于sum即可
将问题转化为我们已经解决过的Two Sum
可以使用while循环跳过重复数字
也可以直接利用set不能包含重复项的特点来防止重复项的出现
总的时间复杂度为O(n^2+nlogn)=(n^2)
这个方法可以推广到k-sum
时间复杂度是O(max{nlogn,n^(k−1)})

注意本题中的不重复指的是所得的三个数不同时重复
而不是一个数值只能出现一次,因此不能用
nums.erase(unique(nums.begin(), nums.end()), nums.end());
对数组进行预处理,因为这会导致结果集的遗漏

注意要先判断,若nums.size() < 3则无须继续
找出3Sum之前,要先sort,不要着眼于去重的过程,而忽略了排序的第一步
去重时的while不要写成if,+1/-1不要误用

4.代码

1)while去重

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

2)set去重

class Solution {public:    vector<vector<int>> threeSum(vector<int>& nums) {        set<vector<int>> result;        if(nums.size() < 3)            return vector<vector<int>>();        sort(nums.begin(), nums.end());        for(int i = 0; i < nums.size() - 2; ++i)        {            if(nums[i] > 0)                break;            int j = i + 1;            int k = nums.size() - 1;            const int target = 0 - nums[i];            while(j < k)            {                if(nums[j] + nums[k] == target)                {                    result.insert({nums[i],nums[j],nums[k]});                    ++j;                    --k;                    // while(j < k && nums[j] == nums[j-1])                    //     ++j;                    // while(j < k && nums[k] == nums[k+1])                    //     --k;                }                else if(nums[j] + nums[k] < target)                {                    ++j;                    // while(j < k && nums[j] == nums[j-1])                    //     ++j;                }                else                {                    --k;                    // while(j < k && nums[k] == nums[k+1])                    //     --k;                }            }        }        return vector<vector<int>>(result.begin(), result.end());    }};