15 3sum
Given an array nums
of n integers, are there elements a, b, c in nums
such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4], A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
思考:1、想了很久,不知道怎么做。只能想到时间复杂度比较高的做法。在网上查到,这个3sum问题是比较经典的,其解法基于2sum。2sum问题是给定一个排好序的数组,问有哪些两个元素相加为
0。解法是一个下标指向第一个,另一个下标指向最后一个。
有如下结论及其规则:
一、如果num[1]+num[n]>0,那么2和n的和大于0,3和n的和也会大于0。等等。所以就没必要再去计算以最后一个为右边界的组合。考虑1,..,n-1这个范围内的组合,即移动后一个。
二、如果num[1]+num[n]<0,那么1和n-1的和,1和n-2的和也会小于0。等等。所以就没必要去计算以1为左边界的组合。考虑2,...,n这个范围内的组合,即移动前一个下标。
不断进行这个操作,最终遍历所有可能的组合,而不是每个组合。
3sum问题可以分解成2sum。取出数组第一个元素X,在剩下的数组里找到两数之和为-X,这就是2sum问题。
由于c语言不支持动态添加元素,所以用c++可能更方便一些,故实现如下。ps:用c语言做了一下,一直free内存那里出问题。
1 class Solution { 2 public: 3 vector<vector<int>> threeSum(vector<int>& nums) { 4 vector<vector<int> > ans; 5 int index1,index2; 6 if(nums.size()<3) return ans; 7 8 sort(nums.begin(), nums.end()); 9 10 for (int i = 0; i <= nums.size()-3; i++) { 11 if(i!=0 && nums[i-1]==nums[i]) continue; 12 13 index1 = i+1; 14 index2 = nums.size()-1; 15 /*if(i==0) { 16 index1 = 1; 17 index2 = nums.size()-1; 18 } 19 else if (i== nums.size()-1) { 20 index1 = 0; 21 index2 = nums.size()-2; 22 }else { 23 index1 = 0; 24 index2 = nums.size()-1; 25 }*/ 26 27 28 while(index1<index2) { 29 if(nums[i]+nums[index1]+nums[index2]==0) { 30 int sol[3] = { nums[i], nums[index1], nums[index2] }; 31 ans.push_back(vector<int> (sol, sol + 3)); 32 //printf("i is %d.index1 is %d.index2 is %d. ", i,index1,index2); 33 index1++;while(nums[index1]==nums[index1-1]) index1++; 34 index2--;while(nums[index2]==nums[index2+1]) index2--; 35 }else if (nums[i]+nums[index1]+nums[index2]>0) { 36 index2--; 37 }else { 38 index1++; 39 } 40 } 41 } 42 return ans; 43 } 44 };
16 3sum closet
Given an array nums
of n integers and an integer target
, find three integers in nums
such that the sum is closest to target
. Return the sum of the three integers. You may assume that each input would have exactly one solution.
Example:
Given array nums = [-1, 2, 1, -4], and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
和上面是简单变形关系,所用的原理一样。因为此次并不需要返回数组的数组,所以又用c语言来表示我的行为。
1 void my_qsort(int *nums, int index1, int index2) { 2 if(index1==index2) return; 3 4 int pre,last; 5 int tmp; 6 7 pre = index1; 8 for(last=index1+1; last<=index2; last++) { 9 if(nums[last]<nums[index1]) { 10 pre++; 11 tmp = nums[pre]; 12 nums[pre] = nums[last]; 13 nums[last] = tmp; 14 } 15 } 16 tmp = nums[index1]; 17 nums[index1] = nums[pre]; 18 nums[pre] = tmp; 19 20 if(pre==index1) { 21 my_qsort(nums, index1+1, index2); 22 }else if(pre==index2) { 23 my_qsort(nums, index1, index2-1); 24 }else { 25 my_qsort(nums, index1, pre-1); 26 my_qsort(nums, pre+1, index2); 27 } 28 29 } 30 31 int threeSumClosest(int* nums, int numsSize, int target) { 32 int ret,index1,index2,tmp; 33 my_qsort(nums, 0, numsSize-1); 34 for(int i = 0; i<numsSize; i++) 35 printf("%d ", nums[i]); 36 printf(" "); 37 ret = nums[0] + nums[1] + nums[2]; 38 for(int i=0; i<=numsSize-3;i++) { 39 index1 = i+1; 40 index2 = numsSize-1; 41 while(index1<index2) { 42 tmp = nums[i] + nums[index1] + nums[index2]; 43 if(tmp == target) return tmp; 44 if(abs(tmp-target)<abs(ret-target)) ret = tmp; 45 if(tmp>target) { 46 index2--; 47 }else if(tmp < target) { 48 index1++; 49 } 50 } 51 } 52 53 return ret; 54 }
18. 4Sum
Given an array nums
of n integers and an integer target
, are there elements a, b, c, and d in nums
such that a + b + c + d = target
? Find all unique quadruplets in the array which gives the sum of target
.
Note:
The solution set must not contain duplicate quadruplets.
Example:
Given array nums = [1, 0, -1, 0, -2, 2], and target = 0. A solution set is: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
思考:首先按一定顺序取前两个数,共有(n-3)*(n-2)个组合,对于剩下的两个数就用首尾指针进行移动检查。
这里我有一个小小的优化。看下line 12行的代码,如果nums[i]大于0,nums[i]>terget,那么后面的三个数一定大于0。既然后面的三个数都大于0,nums[i]加上大于的0
一定大于target。所以就没有必要再继续检查。第15行代码同理。
1 class Solution { 2 public: 3 vector<vector<int>> fourSum(vector<int>& nums, int target) { 4 vector<vector<int>> ans; 5 6 sort(nums.begin(), nums.end()); 7 8 int len = nums.size(); 9 int i,j,k,l; 10 11 for(i=0; i<=len-4; i++) { 12 if(nums[i]>target && nums[i]>=0) continue; 13 if(i>=1 && nums[i]==nums[i-1]) continue; 14 for(j=i+1; j<=len-3; j++) { 15 if(nums[i]+nums[j]>target && nums[j]>=0) continue; 16 if(j>=i+2 && nums[j]==nums[j-1]) continue; 17 k = j + 1; 18 l = len - 1; 19 while(k<l) { 20 if(nums[i]+nums[j]+nums[k]+nums[l]>target) { 21 l--; 22 }else if(nums[i]+nums[j]+nums[k]+nums[l]<target){ 23 k++; 24 }else { 25 int sol[4] = { nums[i], nums[j], nums[k],nums[l] }; 26 ans.push_back(vector<int> (sol, sol + 4)); 27 k++; 28 while(nums[k]==nums[k-1]) k++; 29 l--; 30 while(nums[l]==nums[l+1]) l--; 31 } 32 33 } 34 35 } 36 } 37 return ans; 38 } 39 };