Leetcode找三个数字的和满足xx条件的题目总结15➕16➕259
双指针最基础的题目是一个区间里找两个数字的和等于Target。首先将区间从小到大排序。接下来只要一个le指针,一个ri指针,分别从区间左右边界往中间推进即可。复杂度是排序的nlogn。
下面几道题都是一个区间里找三个数字的和满足xx条件的。这个题目的做法首先还是先排序。之后先固定一个数字,然后在该数字的右侧区间内重新使用之前找两个数字的和的算法。 即i 从0到n-1,j 从i+1开始增加,k 从n-1开始减小直到j和k碰撞。这样的复杂度是n平方。外层i从0到n-1是O(n),内层从i+1到n-1也是O(n)。
15
1 class Solution { 2 public: 3 vector<vector<int>> threeSum(vector<int>& nums) { 4 if(nums.empty()){return vector<vector<int>>();} 5 sort(nums.begin(),nums.end()); 6 vector<vector<int>> res; 7 int n=nums.size(); 8 for(int i=0;i<n;++i){ 9 if(i>0 and nums[i-1]==nums[i]){continue;} 10 int j=i+1,k=n-1; 11 while(j<k){ 12 while(j<k and j>i+1 and nums[j]==nums[j-1]){ 13 ++j; 14 } 15 while(j<k and k<n-1 and nums[k]==nums[k+1]){ 16 --k; 17 } 18 if(j>=k){break;} 19 if(nums[i]+nums[j]+nums[k]>0){ 20 --k; 21 } 22 else if(nums[i]+nums[j]+nums[k]<0){ 23 ++j; 24 } 25 else{ 26 res.push_back({nums[i],nums[j],nums[k]}); 27 ++j,--k; 28 } 29 } 30 } 31 return res; 32 } 33 };
16
1 class Solution { 2 public: 3 int threeSumClosest(vector<int>& nums, int target) { 4 int n=nums.size(); 5 if(n<3){return 0;} 6 sort(nums.begin(),nums.end()); 7 int min_distance=INT_MAX,temp,sum=0; 8 for(int i=0;i<n;++i){ 9 if(i>0 and nums[i]==nums[i-1]){continue;} 10 int j=i+1,k=n-1; 11 while(j<k){ 12 if((temp=nums[i]+nums[j]+nums[k]-target)>0){ 13 if(temp<min_distance){ 14 min_distance=temp; 15 sum=temp+target; 16 } 17 --k; 18 while(j<k and nums[k]==nums[k+1]){ 19 --k; 20 } 21 } 22 else if(temp<0){ 23 if(-temp<min_distance){ 24 min_distance=-temp; 25 sum=temp+target; 26 } 27 ++j; 28 while(j<k and nums[j-1]==nums[j]){ 29 ++j; 30 } 31 } 32 else{ 33 return target; 34 } 35 } 36 } 37 return sum; 38 } 39 };
259
1 class Solution { 2 public: 3 int threeSumSmaller(vector<int>& nums, int target) { 4 int N=nums.size(),res=0; 5 sort(nums.begin(),nums.end()); 6 for(int i=0;i<N-2;++i){ 7 int j=i+1,k=N-1; 8 while(j<k){ 9 if(nums[i]+nums[j]+nums[k]<target){ 10 res+=k-j; 11 j++; 12 } 13 else{ 14 k--; 15 } 16 } 17 } 18 return res; 19 } 20 };
进击的小🐴农