welcome to my blog
LeetCode Top Interview Questions 16. 3Sum Closest (Java版; 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.
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).
第一次做; 排序+双指针; 有序数组上的双指针可以将O(N^2)的循环嵌套遍历降低为O(N)的循环遍历
//先对数组排序, 然后使用双指针; 核心: 双指针在有序数组上移动次数是O(N), 进而将本是O(N^2)的遍历转换成了O(N)的双指针移动
class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int min = Integer.MAX_VALUE;
int res = 0;
for(int i=0; i<=nums.length-3; i++){
int cur = nums[i];
//双指针, 首尾向中间移动;移动原则: sum>target时right--, sum<target时left++ 这个思路挺常用的, 但是没有理解透彻
int left = i+1, right = nums.length-1;
while(left<right){
int sum = cur + nums[left] + nums[right];
//先判断是否需要更新res
int gap = Math.abs(sum-target);
//再调整双指针
if(gap<min){
min = gap;
res = sum;
}
if(sum>target)
right--;
else if(sum<target)
left++;
else
return sum;
}
}
//看清楚了, 返回的是三个数的和
return res;
}
}
第一次做; 暴力, 记录所有三个数的和, 再找出离target最近的一个组合; 细节: 接近程度是靠差的绝对值衡量的, 绝对值越小越接近
//记录所有三个数的和, 再找出离target最近的一个组合
class Solution {
public int threeSumClosest(int[] nums, int target) {
HashMap<Integer,int[]> map = new HashMap<>();
int n = nums.length;
for(int i=0; i<=n-3; i++){
for(int j=i+1; j<=n-2; j++){
for(int k=j+1; k<=n-1; k++){
int sum = nums[i] + nums[j] + nums[k];
map.put(sum, map.getOrDefault(sum, new int[] {nums[i], nums[j], nums[k]}));
}
}
}
//
int final_key=0, min = Integer.MAX_VALUE;
//遍历哈希表
for(Map.Entry<Integer, int[]> e : map.entrySet()){
int sum = e.getKey();
int gap = Math.abs(sum-target);
if(gap<min){
min = gap;
final_key = sum;
}
}
return final_key;
}
}
力扣优秀题解
标签:排序和双指针
本题目因为要计算三个数,如果靠暴力枚举的话时间复杂度会到 O(n^3)O,需要降低时间复杂度
首先进行数组排序,时间复杂度 O(nlogn)
在数组 nums 中,进行遍历,每遍历一个值利用其下标i,形成一个固定值 nums[i]
再使用前指针指向 start = i + 1 处,后指针指向 end = nums.length - 1 处,也就是结尾处
根据 sum = nums[i] + nums[start] + nums[end] 的结果,判断 sum 与目标 target 的距离,如果更近则更新结果 ans
同时判断 sum 与 target 的大小关系,因为数组有序,如果 sum > target 则 end--,如果 sum < target 则 start++,如果 sum == target 则说明距离为 0 直接返回结果
整个遍历过程,固定值为 n 次,双指针为 n 次,时间复杂度为 O(n^2)
总时间复杂度:O(nlogn) + O(n^2) = O(n^2)O(nlogn)+O(n^2)=O(n^2)
class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int ans = nums[0] + nums[1] + nums[2];
for(int i=0;i<nums.length;i++) {
int start = i+1, end = nums.length - 1;
while(start < end) {
int sum = nums[start] + nums[end] + nums[i];
if(Math.abs(target - sum) < Math.abs(target - ans))
ans = sum;
if(sum > target)
end--;
else if(sum < target)
start++;
else
return ans;
}
}
return ans;
}
}