15. 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] ]
解法:如果使用暴力的方法,循环每一个元素组合,那么时间复杂度是O(n3),会出现超时。一定需要想一个方法使得时间复杂度为O(n2)。大致思路如下:
首先,将该数组排序,然后开始遍历数组,在循环中记录与数组当前元素相加等于0的元素component,设置两个指针,第一个指针head指向数组头,
另一个指针tail指向数组尾部。如果head+tail大于component,则tail--,如果head+tail小于component,则head++;如果head+tail等于component,则加入vector中。
当head==tail时,循环结束。这里有一个地方需要注意的是,不能存在重复的答案,比如[-1,-1,2]和[-1,2,-1]就是重复的答案。因为我们的数组是有序的,
所以如果数组中下一个元素等于已有答案中的元素,则删除。所以该算法的时间复杂度为O(n2) 。具体代码如下所示:
class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { sort(nums.begin(), nums.end()); vector<vector<int> > result; for (int i = 0; i<nums.size(); i++){ //一层循环 int head = i + 1, tail = nums.size() - 1; int component = 0 - nums[i]; while (head<tail){ //两层循环,下面的while只是这个while的一部分,所以时间复杂度为O(n*n) if (component>nums[head] + nums[tail]){ head++; } else if (component<nums[head] + nums[tail]){ tail--; } else{ vector<int> r; r.push_back(nums[i]); r.push_back(nums[head]); r.push_back(nums[tail]); result.push_back(r); //因为数组中可能存在相同的元素,需要把相同的元素去掉 //去掉重复的第二个数字 head++; while (head<tail&&nums[head] == r[1]) head++; //去掉重复的第三个数字 tail--; while (head<tail&&nums[tail] == r[2]) tail--; } } //去掉重复的第一个数字 while (i + 1<nums.size() && nums[i] == nums[i + 1]) i++; } return result; } };