标签:array, medium
问题描述
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.
给定包含n个整数的数组nums和整数target,在数组中寻找3个整数,使得3个整数的和与target的值最接近。返回3个整数的和。假设每个输入只有一个解。
例子:
给定数组nums = [-1, 2, 1, -4]和target = 1。
最接近target值的和是2 (-1 + 2 + 1 = 2)。
解决方案
方法一:暴力方法
遍历数组中的任意3个元素,计算其和以及与target的差,选取差最小的和。
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int len = nums.size();
int minDiff = INT_MAX;
int closestSum = 0;
for(int i = 0; i < len - 2; i++) {
for(int j = i + 1; j < len - 1; j++) {
for(int k = j + 1; k < len; k++) {
int sum = nums[i] + nums[j] + nums[k];
int diff = target > sum ? target - sum : sum - target;
if(diff < minDiff) {
minDiff = diff;
closestSum = sum;
}
}
}
}
return closestSum;
}
};
算法分析
- 运行时间:256 m
- 时间复杂度:Θ(n3)。
方法二:排序法
首先对数组进行排序。接着,选定一个元素i作为第一个元素。然后,从数组两端向中间遍历,选取剩下的两个元素j和k。
如果A[i] + A[k] + A[j]的值小于target,则增加j的索引,否则减少k的索引。因为数组是有序的,这里有三种情况:
- A[j] + A[k] == target - A[i],此时三个元素的和等于target,差值最小;
- A[j] + A[k] < target - A[i],因此需要增加j的索引,使值增加。
- A[j] + A[k] > target - A[i],此时只有减少k的索引,才能减少两个元素的和值。
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int len = nums.size();
int minDiff = INT_MAX;
int closestSum = 0;
sort(nums.begin(), nums.end());
for(int i = 0; i < len - 2; i++) {
int j = i + 1;
int k = nums.size() - 1;
while(j < k) {
int sum = nums[i] + nums[j] + nums[k];
int diff = sum - target > 0 ? sum - target : target - sum;
if (diff < minDiff) {
minDiff = diff;
closestSum = sum;
}
int sum2 = nums[j] + nums[k];
if (sum2 > target - nums[i]) {
k--;
} else if (sum2 < target - nums[i]) {
j++;
} else {
break;
}
}
}
return closestSum;
}
};
算法分析
- 程序运行时间:12ms
- 排序算法的复杂度为O(nlog(n)),for循环的复杂度为O(n2)。因此,算法的整体时间复杂度为O(n2)。