自己的思路是将解的情况分类:只有三种情况 (正,0,负),(正,正,负),(负,负,正)。
将nums分为两个数组pos,保存正数;neg,保存负数。
当两个数组的长度小于nums的长度时说明存在0,这个时候利用哈希的方法可以找到第一种情况的所有解;
对于第二种情况,构建set:possum,保存两个不同正数的和,然后利用哈希的方法去neg中寻找;
第三种情况和第二种类似。
判题的时候发现这样无法处理:全0,会直接输出为空、有重复的正数或负数,会出现重复的元组。
看解析
哈希的方法是自己想复杂了,构建两轮循环确定a,b,然后哈希寻找-a-b就可以了,难点也确实就在于去重
然后是双指针的方法
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> res;sort(nums.begin(), nums.end() );for(int i = 0; i < nums.size(); ++i ){if( nums[i] > 0 )return res;//上一轮成立的解的下标是 i-1,left, right//, 因此如果这一轮的nums{i] 和nums[i-1]相等就要去重if(i > 0 && nums[i] == nums[i-1])continue;//这里指针的初始化也要注意,起始三元组是 最小负数(i),第二小负数(left),最大正数(right)//这样就保证了每次left和right的移动都有可能找到潜在的解//通过三个指针的移动来保证所有的三元组都能搜索到int left = i + 1;int right = nums.size() - 1;while(left < right){if( nums[i] + nums[left] + nums[right] < 0 )//当前三元组的和偏小,需要增大负数left++;else if ( nums[i] + nums[left] + nums[right] > 0 )//当前三元组的和偏大,需要减小正数right--;else {res.push_back( vector<int> {nums[i], nums[left], nums[right]} );//只有等于0的解才需要去重//去重,当前符合要求的解是i,left,right,因此要比较下一次可能移动到的位置while( left < right && nums[right-1] == nums[right] ) right--;while( left < right && nums[left+1] == nums[left] ) //去重left++;//由于此时是一组和为0的解,因此为了寻找下一组可能的解,left和right必须都要移动right--;left++;//只要当得到一组新的三元组,即不出现重复时,才重新开始判断}} }return res;}
};