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