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).
这道题開始思路没理顺,后来发现能够进行转化成两个数和的问题。
先考虑两个数和最接近target的问题,这个问题对于排序好的数组非常好求解。使用两个指针。一个指针初始指向数组的第一个元素,一个指针初始指向最后一个元素。然后当这两个指针的值比target小时左边指针右移。值比target大时右边的指针左移,值和target同样时表示找到了和为target的两个数能够直接返回了。这样在O(N)的时间内就能够找到和最接近target的值,可是前提是排序好的数组。
针对这道求数组中3个数的和最接近target的问题,能够这么分析:首先将数组排序;然后遍历数组中的每个元素(如果这个指针为first)。那么原来的问题能够理解成了在[fist+1,last]的区间内查找和为target-*first的两个数的问题了。这样就能够在O(N^2)的时间内求解了。
代码例如以下:
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
//首先进行排序
sort(nums.begin(),nums.end());
//须要三个指针,第一个指针指向一个值时,第二个指针和第三个指针进行变化。将三个数的和转化成两个数的和的问题
vector<int>::iterator first=nums.begin();
vector<int>::iterator second;
vector<int>::iterator last;
//開始用排序后的前3个数来初始化返回值
int closeResult=*first+*(first+1)+*(first+2);
//从头開始遍历排序后的数组。每次固定一个值,然后在剩下的数组中从两头開始遍历。找到符合要求的值
for(;first<nums.end()-2;first++)
{
second=first+1;
last=nums.end()-1;
int result=target-*first;
//以下即在[second,last]这个数组中寻找和最接近result的两个数
while(second<last)
{
if(abs(*second+*last-result)<abs(closeResult-target))
closeResult=*first+*second+*last;
if((*second+*last)<result)
second++;
else if((*second+*last)>result)
last--;
else
return target;
}
}
return closeResult;
}
};
runtime:16ms