中文题目
给定一个包括 n 个整数的数组 nums
和 一个目标值 target
。找出 nums
中的三个整数,使得它们的和与 target
最接近。返回这三个数的和。假定每组输入只存在唯一答案。
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
英文题目
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.
Example:
Given array nums = [-1, 2, 1, -4], and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
解法一:
此题与15题颇为相似,做过了15题之后面对此题,我想,二者的解题思路应该一致,即排序后再进行匹配寻找,已知了较为快速的解法,我刚开始索性就先采用了暴力求解的策略,结果。。。过了。。。
代码:
int threeSumClosest(int* nums, int numsSize, int target) {
int i, j, k, sum, max = 62233;
for (i = 0; i < numsSize-2; i++) {
for (j = i + 1; j < numsSize-1; j++) {
for (k = j + 1; k < numsSize; k++) {
if (abs(nums[i] + nums[j] + nums[k] - target) < max) {
max = abs(nums[i] + nums[j] + nums[k] - target);
sum = nums[i] + nums[j] + nums[k];
}
}
}
}
return sum;
}
直接采用三循环的暴力求解,让人意外的是,通过了。。。虽然用时感人
解法二:
同第十五题,先进行一次排序,之后再进行处理
代码:
void Merge(int a[], int l, int r, int rightEnd, int temp[]){
int leftEnd = r-1 ;
int left = l, tmp = l;
while (l <= leftEnd && r <= rightEnd){ // 当左右子序列均不空
if (a[l] > a[r])
temp[tmp++] = a[r++];
else
temp[tmp++] = a[l++];
}
while (l <= leftEnd)
temp[tmp++] = a[l++];
while (r <= rightEnd)
temp[tmp++] = a[r++];
for (int i = left; i < rightEnd + 1; i++)
a[i] = temp[i];
}
void MergeSort(int a[], int l, int rightEnd, int temp[]) {
int center;
if (l < rightEnd) {
center = (l + rightEnd) / 2;
MergeSort(a, l, center, temp);
MergeSort(a, center + 1, rightEnd, temp);
Merge(a, l, center+1, rightEnd, temp);
}
}
void Merge_sort(int a[], int n){
int* tmpA;
tmpA = malloc(n * sizeof(int));
if (tmpA != NULL){
MergeSort(a, 0, n-1, tmpA);
free(tmpA);
} else {
printf("ERROR");
}
}
int threeSumClosest(int* nums, int numsSize, int target) {
int i = 0, j, k, temp = 65533, sum;
Merge_sort(nums, numsSize);
for (i = 0; i < numsSize; i++){
if (i > 0 && nums[i] == nums[i-1])
continue;
j = i+1;
k = numsSize-1;
while (j < k){
if (abs(nums[i]+nums[j]+nums[k]-target) < temp){
temp = abs(nums[i]+nums[j]+nums[k]-target);
sum = nums[i] + nums[j] + nums[k];
if (nums[i]+nums[j]+nums[k] > target) { // 之和过大 k--
k--;
continue;
}
else if (nums[i]+nums[j]+nums[k] < target) {// 之和过小 j++
j++;
continue;
}
else // 等于直接返回即可
return sum;
}
if (nums[i]+nums[j]+nums[k] > target)// 之和过大 k--
k--;
else if (nums[i]+nums[j]+nums[k] < target)// 之和过小 j++
j++;
}
}
return sum;
}
代码说明:
基本原理和15题相同,只是在判断之时略有改动,所以不再赘述
改进之后时间也算是快了许多,如下: