解题思路
Step1:先对数组排序,然后设置3个指针,指针1遍历范围为(0~数组长度减2)。
Step2:指针1位置确定时,指针1后面的数组元素首位各放置一个指针(指针2、指针3)。
Step3:如果三数之和=target,则返回target值;如果三数之和<target,则将指针2往后移动,如果三数之和>target,则将指针3往前移动。
Step4:当指针2和指针3重合时,则将指针1往后移动。
Step5:重复 Step2 到 Step4。直到指针1遍历完。
Java代码
import java.util.Arrays;
public class ThreeSumClosest {
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.threeSumClosest(new int[]{-1, 2, 1, -4}, 1));
}
}
class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int n = nums.length;
int min_diff = Integer.MAX_VALUE;//当前找到的三数之和与target的最小差值
int ans = 0;//最小差值对应的三数之和
int cur_sum = 0;
int cur_diff = 0;
for (int i = 0; i < n - 2; i++) {
//优化一:如果有重复元素则跳过
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
//优化二:如果加上最后面两个数依旧没有target大,则判断一下三数之和之后跳过当前循环
cur_sum = nums[i] + nums[n - 2] + nums[n - 1];
if (target >= cur_sum) {
cur_diff = target - cur_sum;
if (cur_diff == 0) {
return target;
}
if (cur_diff < min_diff) {
ans = cur_sum;
min_diff = cur_diff;
}
continue;
}
//优化三:前面3个数的和已经>=target,则判断三数之和之后跳出循环
cur_sum = nums[i] + nums[i + 1] + nums[i + 2];
if (target <= cur_sum) {
cur_diff = cur_sum - target;
if (cur_diff == 0) {
return target;
}
if (cur_diff < min_diff) {
ans = cur_sum;
}
break;
}
int j = i + 1, k = n - 1;
while(j < k){
cur_sum = nums[i] + nums[j] + nums[k];
if (cur_sum == target) {
return target;
}
cur_diff = target - cur_sum;
if (cur_sum < target) {
if (cur_diff < min_diff) {
ans = cur_sum;
min_diff = cur_diff;
}
j++;
} else { //cur_sum > target
cur_diff = -cur_diff;
if (cur_diff < min_diff) {
ans = cur_sum;
min_diff = cur_diff;
}
k--;
}
}
}
return ans;
}
}
Python代码
class Solution(object):
def threeSumClosest(self, nums, target):
nums = sorted(nums) # or nums.sort()
n = len(nums)
min_diff = float('inf')
ans = 0
for i in range(n-2):
# 优化一:如果有重复元素则跳过
if i > 0 and nums[i] == nums[i-1]:
continue
# 优化二:如果加上最后面两个数依旧没有target大,则判断一下三数之和之后跳过当前循环
cur_sum = nums[i] + nums[n - 2] + nums[n - 1]
if target >= cur_sum:
cur_diff = target - cur_sum
if cur_diff == 0:
return target
if cur_diff < min_diff:
ans = cur_sum
min_diff = cur_diff
continue
# 优化三:前面3个数的和已经>=target,则判断三数之和之后跳出循环
cur_sum = nums[i] + nums[i + 1] + nums[i + 2]
if target <= cur_sum:
cur_diff = cur_sum - target
if cur_diff == 0:
return target
if cur_diff < min_diff:
ans = cur_sum
break
j, k = i + 1, n - 1
while j < k:
cur_sum = nums[i] + nums[j] + nums[k]
if cur_sum == target:
return target
cur_diff = target - cur_sum
if cur_sum < target:
if cur_diff < min_diff:
ans = cur_sum
min_diff = cur_diff
j += 1
else:
cur_diff = -cur_diff
if cur_diff < min_diff:
ans = cur_sum
min_diff = cur_diff
k -= 1
return ans
if __name__ == '__main__':
sol = Solution()
print(sol.threeSumClosest([-1, 2, 1, -4], 1)) # 2
完整题目
16. 最接近的三数之和
给你一个长度为 n
的整数数组 nums
和 一个目标值 target
。请你从 nums
中选出三个整数,使它们的和与 target
最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。
示例 1:
输入:nums = [-1,2,1,-4], target = 1 输出:2 解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
示例 2:
输入:nums = [0,0,0], target = 1 输出:0
提示:
3 <= nums.length <= 1000
-1000 <= nums[i] <= 1000
-10^4 <= target <= 10^4