第一部分分析3Sum問題,第二部分分析3Sum Closest問題,因爲兩個問題的思路很像,因此這裏放到一塊兒分析。
其中3Sum問題好像仍是計算機科學領域暫未解決的問題之一,固然,還沒找到更好的解決方案。git
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.github
Note:
Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
The solution set must not contain duplicate triplets.算法
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)
說的意思很簡單,就是:給出一個整型數組,從裏面找三個數 a ,b ,c
而且使 a+b+c=0
。找出全部符合條件的三元組解集。而且解集中不能出現重複的解。數組
class Solution { public: vector<vector<int> > threeSum(vector<int> &num) { vector<vector<int> > res; if(num.size()<3) return res;//參數檢驗 sort(num.begin(),num.end()); //先排序 int beg , end , sum; vector<int> tmp(3,0); for(int i = 0;i<num.size()-2;++i){ // 去除重複數字的再次查找,避免結果集合中出現重複解 if(num[i]>0)break; if((i>0) && num[i]==num[i-1]) continue; beg = i + 1; end = num.size()-1; while(beg < end){ sum=num[beg] + num[end] + num[i]; if( sum< 0) ++beg; else if(sum > 0) --end; else{ tmp[0] = num[i]; tmp[1] = num[beg]; tmp[2] = num[end]; res.push_back(tmp); // 一樣是去除重複數字的再次查找,避免結果集合中出現重複解 while(beg<end && num[beg]==tmp[1]) ++beg; while(beg<end && num[end]==tmp[2]) --end; if(beg>=end) break; } } } return res; } };
sort(S); for i=0 to n-3 do a = S[i]; start = i+1; end = n-1; while (start < end) do b = S[start]; c = S[end]; if (a+b+c == 0) then output a, b, c; // Continue search for all triplet combinations summing to zero. start = start + 1 end = end - 1 else if (a+b+c > 0) then end = end - 1; else start = start + 1; end end end
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.測試
For example, given array S = {-1 2 1 -4}, and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
說的意思很簡單,就是:給出一個整型數組,從裏面找三個數 a ,b ,c
而且使 a+b+c=0
。找出全部符合條件的三元組解集。而且解集中不能出現重複的解。spa
sum != target
則判斷當前兩數之間的距離 dt=abs(sum-target)
和目前已求得的最短距離 dis
哪一個更小,若是 dt<dis
,則說明出現了一個更接近 target 的解。則記錄下此解的和 res 。class Solution { public: int threeSumClosest(vector<int> &num, int target) { int n=num.size(); if(n<3)return 0; sort(num.begin(),num.end()); int beg,end,sum=0; int dis=INT_MAX; int res; for(int i=0;i<n-2;++i){ beg=i+1; end=n-1; while(beg<end){ sum=num[i]+num[beg]+num[end]; if(sum==target)return sum; else if(sum<target) ++beg; else --end; int dt=(abs(sum-target)); if(dis>dt){ dis=dt; res=sum; } } } return res; } };
newTarget = target - (num[start]+num[end])
,再使用二分查找查找剩下的那個數字。使用的二分查找返回的數字是找到的比較符合條件的數組中數字的下標。class Solution { // 二分查找 int findTarget(vector<int> &num, int start, int end, int target) { if (start==end) return start; if (end-start==1) return abs(num[end]-target) > abs(num[start]-target) ? start : end; int mid = (start+end)/2; if (num[mid]==target) return mid; else if(num[mid]>target) return findTarget(num, start, mid, target); else return findTarget(num, mid, end, target); } public: int threeSumClosest(vector<int> &num, int target) { int res=0; if(num.size()<=3){ for(auto v : num) res+=v; return res; } sort(num.begin(), num.end()); int start = 0; int end = int(num.size()-1); int mindiff = INT_MAX; while (start<end-1) { int newTarget = target - (num[start] + num[end]); int p = findTarget(num, start+1, end-1, newTarget); int curSum = num[start] + num[end] + num[p]; if (curSum == target) { return target; }else if(curSum > target) end--; else start++; mindiff = abs(mindiff)>abs(target-curSum) ? target-curSum : mindiff; } res=target-mindiff; return res; } };