008-在一个数组里找三个数的和最接近目标值
2020-05-13 本文已影响0人
Woodlouse
描述
在一个包含n个整数的数组S中,查找三个整数,使得这三个整数的和最接近给定值target,假设数组里只有一组这样的数字,写一个函数,返回这三个整数的和。
例如:输入数组S={-1, 2, 1, -4},目标值target = 1,最接近目标值的和是2,(-1 + 2 + 1 = 2)。
分析
最简单粗暴的方式是把数组里所有的数字三个三个的相加,得出所有的数值后和然后和目标值比较,得出结果。伪代码如下:
target = 1;
dis = INT_MAX;
result = INT_MAX;
for i=0 -> n-2:
for j=i+1 -> n-1:
for k=j+1 -> k:
sum = a[i] + a[j] + a[k];
curDis = abs(sum - target)
if curDis < dis:
dis = curDis;
result = sum;
不难看出,此种方法的时间复杂度为O(),空间复杂度为O(1);
有没有降低一些时间复杂度的操作呢?如果把数组排序后有没有可能降低时间复杂度?
在有序数组中,设定三个游标a、b和c:
- 初始值a=0,b=a+1,c=n-1
- 计算a、b和c三个位置元素的和,计算和目标值的差值,差值小于当前的差值则进行替换;
- 和值大于目标值,c游标向前移动(--c),和值小于目标值b游标向后移动(++b);
- 结束条件:b>=c
依据以上分析,代码如下:
int threeSumColset(vector<int> &num, int target)
{
int result = INT_MAX;
int gap = INT_MAX;
sort(num.begin(), num.end());
for (auto a=num.begin(); a!=prev(num.end(), 2); ++a) {
auto b = next(a);
auto c = prev(num.end());
while (b < c) {
int sum = *a + *b + *c;
int curGap = abs(sum - target);
if (curGap < gap) {
gap = curGap;
result = sum;
}
if (sum < target) {
++b;
} else {
--c;
}
}
}
return result;
}
可以看出时间复杂度为O(),空间复杂度为O(1)。