一.题目描写叙述
二.解题技巧
该题与3Sum的要求类似。不同的是要求选出的组合的和与目标值target最接近而不一定相等。但实际上,与3Sum的算法流程思路类似,先是进行排序。然后顺序选择数组A中的下标为i的元素值作为组合中三个数的最小值,进而寻找另外两个更大的值,最后求出三个数的和。只是的地方在于这里是寻找最靠近给定值。寻找最靠近的值就无全部反复的事情了,所以能够不考虑夹逼的过程中的越过同样元素的过程,尽管越过同样的元素速度会快一些,可是代码长度也会加长。
这道题难的地方可能在于刚開始这样的差的阈值的过程,假设把阈值设置得太小了。会出现错误,因此,应该尽可能地将阈值设置得大一点。因为数组是已经排序的,因此。数组中三个数的和的范围在[3*A[0], 3*A[n-1]]。因此,阈值能够依据以下三种情况进行设置:
1.if target >= 3*A[n-1],阈值设置为H = target - 3 * A[0];
2.if 3*A[0] <= target<3*A[n-1],阈值设置为H = 3 * A[n-1] - 3*A[0];
3.if target < 3 * A[0],阈值设置为H = 3 * A[n-1] - target。
这样就能够依据阈值与眼下得到的三个数的和与target的差来推断是否是最接近target的情况了。依据不同的情况,选择缩放的方向。
三.演示样例代码
class Solution
{
public:
int threeSumClosest(vector<int> &num, int target)
{
int Size = num.size();
sort(num.begin(), num.end());
int MaxSum = 3 * num[Size - 1];
int MinSum = 3 * num[0];
int ThreadHold = 0;
if (target <= MinSum)
{
ThreadHold = MaxSum - target;
}
if (MaxSum < target)
{
ThreadHold = target - MinSum;
}
if ((MinSum < target) && (target <= MaxSum))
{
ThreadHold = MaxSum - MinSum;
}
int Result = 0;
for (int Index_outter = 0; Index_outter < (Size - 2); Index_outter++)
{
int First = num[Index_outter];
int Second = num[Index_outter + 1];
if ((Index_outter != 0) && (First == num[Index_outter - 1]))
{
continue;
}
int Start = Index_outter + 1;
int End = Size - 1;
while (Start < End)
{
Second = num[Start];
int Third = num[End];
int Sum = First + Second + Third;
if (Sum == target)
{
return Sum;
}
if (Sum < target)
{
Start++;
if (ThreadHold >= (target - Sum))
{
Result = Sum;
ThreadHold = target - Sum;
}
}
if (Sum > target)
{
End--;
if (ThreadHold >= (Sum - target))
{
Result = Sum;
ThreadHold = Sum - target;
}
}
}
}
return Result;
}
};
四.总结
这道题最难的地方在于阈值的选择上面,事实上能够设置为整数的最大值的,可是。我一開始并不知道怎样计算整数的最大值,因此。仅仅能依据排好序的数组的三个数的和的范围与target的关系来设定阈值了。详细的阈值设置情况能够画个数轴出来分析,画出数轴之后。一切就明显了。
原文:http://www.cnblogs.com/slgkaifa/p/7397834.html