题目
这道题看似和两数之和的的哈希法,但用哈希比较麻烦
分析
双指针
1 class Solution { 2 public: 3 4 vector<vector<int>> threeSum(vector<int>& nums) { 5 vector<vector<int>>res; 6 sort(nums.begin(),nums.end()); 7 for(int i = 0;i < nums.size();i++){ 8 if(nums[i] > 0 ) return res; 9 if(i > 0 && nums[i] == nums[i-1]) continue; 10 int left = i+1,right = nums.size()-1; 11 while(left < right){ 12 if(nums[i] + nums[left] + nums[right] > 0) right--; 13 else if(nums[i] + nums[left] + nums[right] < 0) left++; 14 else{ 15 res.push_back(vector<int>{nums[i],nums[left],nums[right]}); 16 while(left < right && nums[right] == nums[right-1]) right--; 17 while(left < right && nums[left] == nums[left+1]) left++; 18 left++; 19 right--; 20 } 21 } 22 23 } 24 25 return res; 26 27 } 28 };
时间复杂度O(N2) ,空间复杂度O(logN)。我们忽略存储答案的空间,额外的排序的空间复杂度为 O(logN)。我们修改了输入的数组 extit{nums}nums,在实际情况下不一定允许,因此也可以看成使用了一个额外的数组存储了 nums 的副本并进行排序,空间复杂度为 O(logN)
注意:
1. 第九行的去重逻辑应该是如果该元素和上一个元素相同,那么就不考虑这个元素。去重逻辑不应该是下一个元素和当前相同,如果
这样考虑将会导致忽略开头元素相同的情况,如-1,-1,2
2. 第十六十七行的去重逻辑应该再找到一个三元组后,而不应该放在之前
3. 双指针之前一般要排序。
4. 三数之和可以用双指针,那么LeetCode1.两数之和可不可以用双指针呢 ?怎么改就能用了呢?
因为两数之和那个题是要返回索引和数值所以不能用双指针,用map哈希。若按照本题将两数之和改成返回数组元素,则可以用双指
针,代码如下。
1 vector<vector<int>> tSum(vector<int>& nums, int target) { 2 vector<vector<int>> res; 3 sort(nums.begin(),nums.end()); 4 int left = 0,right = nums.size()-1; 5 while(left < right){ 6 if(nums[left] > targrt || nums[right] < target ) return res; 7 if(nums[left] + nums[right] < target){left++;} 8 else if(nums[left] + nums[right] > target) {right--;} 9 else { 10 res.push_back(vector<int>{nums[left],nums[right]}); 11 while(left < right && nums[right] == nums[right-1]) right--; 12 while(left < right && nums[left] == nums[left+1]) left++; 13 right--; 14 left++; 15 } 16 } 17 return res; 18 }
这里几乎思路一样,只用外部一个循环就可以。
时间复杂度为O(nlogn),因为找两数的循环的时间复杂度为O(n),C++stl中的排序为改进后的快速排序时间复杂度为O(nlogn),所以取排序时间复杂度
这样可以看出在求解两数之和问题时,一般用哈希,因为若用双指针时间复杂度变高了。