给你一个长度为 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
-104 <= target <= 104
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/3sum-closest
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
- class Solution {
- public int threeSumClosest(int[] nums, int target) {
- // return threeSumClosestI(nums, target);
- return threeSumClosestII(nums, target);
- }
-
- //方法二:双指针
- //与三数之和思路类似,先排序,利用双指针优化空间
- //遍历过程中对于每个三数之和都要比较它和目标值的差值的绝对值
- //时间复杂度O(N^2),空间复杂度O(1)
- private int threeSumClosestII(int[] nums, int target) {
- if (nums == null || nums.length == 0) {
- return 0;
- }
- //先排序
- Arrays.sort(nums);
- int min = nums[0] + nums[1] + nums[2];
- for (int i = 0; i < nums.length - 2; i++) {
- if (i > 0 && nums[i] == nums[i - 1]) {
- continue;
- }
- int left = i + 1, right = nums.length - 1;
- while (left < right) {
- int sum = nums[i] + nums[left] + nums[right];
- if (sum == target) {
- return target;
- }
- if (Math.abs(min - target) > Math.abs(sum - target)) {
- min = sum;
- }
- if (sum > target) {
- right--;
- // while (left < right && nums[right] == nums[right + 1]) {
- // right--;
- // }
- } else {
- left++;
- //left先+1之后,和它前面的left-1进行比较,若后+1,则和它后面的left+1进行比较
- // while (left < right && nums[left] == nums[left - 1]) {
- // left++;
- // }
- }
- }
- }
- return min;
- }
-
- //方法一:暴力解法,穷举所有可能
- //时间复杂度O(N^3),空间复杂度O(1)
- private int threeSumClosestI(int[] nums, int target) {
- if (nums == null || nums.length == 0) {
- return 0;
- }
- int minDiff = Integer.MAX_VALUE;
- int result = nums[0] + nums[1] + nums[2];
- for (int i = 0; i < nums.length - 2; i++) {
- for (int j = i + 1; j < nums.length - 1; j++) {
- for (int k = j + 1; k < nums.length; k++) {
- int sum = nums[i] + nums[j] + nums[k];
- int diff = Math.abs(sum - target);
- if (diff < minDiff) {
- minDiff = diff;
- result = sum;
- }
- }
- }
- }
- return result;
- }
- }