版权声明:版权所有,转载请注明原网址链接。 https://blog.csdn.net/qq_41231926/article/details/82177199
原题链接:https://leetcode-cn.com/problems/3sum-closest/description/
题目描述:
知识点:数组、对撞双指针
思路一:暴力解法
三重循环遍历nums数组。时间复杂度是O(n ^ 3),其中n为数组nums的长度。空间复杂度是O(1)。
JAVA代码:
public class Solution {
public int threeSumClosest(int[] nums, int target) {
int n = nums.length;
int diff = Integer.MAX_VALUE;
int result = 0;
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
for(int k = j + 1; k < n; k++) {
if(Math.abs(nums[i] + nums[j] + nums[k] - target) < diff) {
diff = Math.abs(nums[i] + nums[j] + nums[k] - target);
result = nums[i] + nums[j] + nums[k];
}
}
}
}
return result;
}
}
LeetCode解题报告:
思路二:第一个指针从前往后遍历,另外两个指针在第一个指针设定的范围内对撞查找
本题和LeetCode15——三数之和很像,其实本题比LeetCode15要简单,因为本题只需要求出与target最接近的三个数的和,而不用去管这三个数的组合是否重复。参照LeetCode15的解题思路,我们依然可以使用对撞双指针来解决我们的问题。关于LeetCode15——三数之和的JAVA题解,可以参见我的另一篇博文:https://blog.csdn.net/qq_41231926/article/details/81449878。
首先,得对数组nums进行排序。设立一个指针i从前往后一直遍历排序后的nums数组,直到倒数第三个元素。因为如果到了倒数第二个元素,那么后面就只剩下一个元素,取不满三个元素了。接着就是我们的滑动窗口法遍历排序后数组中索引为i + 1到n - 1范围内的元素,其中n为数组nums的长度,根据题意来实现我们的算法。注意,对撞双指针left和right的变动应当发生在对当前三个元素之和的结果处理之后。
排序的时间复杂度是O(nlogn)。在遍历过程中内部循环由于使用了对撞双指针做优化,因此时间复杂度是O(n ^ 2)级别的。总的时间复杂度是O(n ^ 2)级别的。这个思路中没有使用额外的空间,空间复杂度是O(1)级别的。
JAVA代码:
public class Solution {
public int threeSumClosest(int[] nums, int target) {
int n = nums.length;
int diff = Integer.MAX_VALUE;
int result = 0;
Arrays.sort(nums);
for(int i = 0; i < n - 2; i++) {
int left = i + 1;
int right = n - 1;
while(left < right) {
if(nums[i] + nums[left] + nums[right] < target) {
if(Math.abs(nums[i] + nums[left] + nums[right] - target) < diff) {
diff = Math.abs(nums[i] + nums[left] + nums[right] - target);
result = nums[i] + nums[left] + nums[right];
}
left++;
}else if(nums[i] + nums[left] + nums[right] == target) {
return target;
}else {
if(Math.abs(nums[i] + nums[left] + nums[right] - target) < diff) {
diff = Math.abs(nums[i] + nums[left] + nums[right] - target);
result = nums[i] + nums[left] + nums[right];
}
right--;
}
}
}
return result;
}
}
LeetCode解题报告: