之前没有把三数之和整理,今天把two sum,three sum, four sum 都发出来
我的第一感觉就是:仿照two sum的哈希方法,表示nums,然后双重循环,时间复杂度O(n2),然而由于leetcode挂掉,我的代码丢了,如果能找回来再贴:
先贴优化过的解:
C++解法二:
1 class Solution { 2 public: 3 vector<vector<int>> threeSum(vector<int>& nums) { 4 vector<vector<int>> res; 5 //对数组进行排序,便于节省搜索 6 sort(nums.begin(),nums.end()); 7 //对不成立的情况实现做出判断节省时间 8 if(nums.empty()||nums.back()<0||nums.front()>0) return {}; 9 //对数组从小到大进行遍历,遍历到大于0的数就停止 10 for(int k=0;k<nums.size();k++){//先遍历找到要fix的那个数 11 if(nums[k]>0) break; 12 if(k>0 && nums[k]==nums[k-1]) continue;//短路表达式 13 int target=0-nums[k]; 14 int i=k+1,j=nums.size()-1; 15 while(i<j){ 16 if(nums[i]+nums[j]==target){ 17 res.push_back({nums[k],nums[i],nums[j]}); 18 while(i<j && nums[i]==nums[i+1]) ++i;//短路表达式 19 while(i<j && nums[j]==nums[j-1]) --j;//短路表达式 20 ++i;--j; 21 }else if(nums[i]+nums[j]<target){ 22 ++i; 23 }else { 24 --j; 25 } 26 } 27 } 28 return res; 29 } 30 };
思路如下:
由于需要找三个数,而且之和为0,必然有正有负,首先对nums进行排序,降低搜索的复杂度
并且首先对不成立的情况实现做出判断节省时间。
然后,思想是先fix一个数nums[k],然后查找另外两个数,使得他俩的和为0-nums[k];
先从头,对所有的不大于零的数进行遍历,并且对一个数只fix一次(防止重复答案出现);这是因为如果要找到三个和为0 的数,除了000这种情况,最左边的数一定为负数,所以只需遍历fix所有不大于0的数即可
然后,从nums[k]之后的数组的首尾两端分别遍历找另外两个元素,如下图:
可知i和j搜索次数加起来为剩下的数组长度;总得时间O(n2)级别。
除此之外,还要注意,在找到正确答案之后,要跳过和nums[i]和nums[j]两个数相等的数,因为这些数会导致答案重复,所以先行跳过避免重复。