最接近的三数之和
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
示例:
输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
提示:
3 <= nums.length <= 10^3
-10^3 <= nums[i] <= 10^3
-10^4 <= target <= 10^4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum-closest
解题思路
暴力解法
根据题目可以知道,一定是三个数的和。因此可以对数组进行三次遍历。并且使用两个临时变量存储结果值和结果值与target差值的绝对值。将每一层遍历的元素累加,与target进行判断。取与target差值的绝对值最小的值。
代码
func threeSumClosest(nums []int, target int) int {
result,diff := 0,math.MaxInt64
for i:=0;i<len(nums);i++{
for j:=i+1;j<len(nums);j++{
for k:=j+1;k<len(nums);k++{
sum := nums[i] + nums[j] + nums[k]
tmp := int(math.Abs(float64(sum - target)))
if tmp < diff {
diff = tmp
result = sum
}
}
}
}
return result
}
进阶做法
暴力解法是使用三层循环。优化的思路是减少循环的层数,因为考虑到三层循环可以相当于指导一个数,然后再对接下来的数组进行双指针运算可以代替三层循环。使用双指针之前应先将数组进行排序。进阶的难点在于使用双指针之后,如何驱动指针的指向。
这里我也是用两个临时变量:result和diff,result用来存储结果值,diff用来存储结果值和目标值之差的绝对值。x表示头指针,y表示尾指针。sum = nums[i] + nums[x] +nums[y]
- 如果sum > target。因此为了让结果值接近,可以将y--。这里判断一下是否需要更新result和diff值。
- 如果sum < target。因此为了让结果接近,可以将x++。这里也判断一下是否需要更新result和diff值。
- 如果sum==target。直接跳出循环,因为相等了就是最接近的了。
代码
func threeSumClosest(nums []int, target int) int {
result,diff := 0,math.MaxInt64
sort.Ints(nums)
for i:=0;i<len(nums);i++{
x := i+1
y := len(nums)-1
for x<y {
sum := nums[i] + nums[x] + nums[y]
if sum < target {
tmp := int(math.Abs(float64(sum - target)))
if tmp <= diff {
result = sum
diff = tmp
}
x++
}else if sum > target {
tmp := int(math.Abs(float64(sum - target)))
if tmp <= diff {
result = sum
diff = tmp
}
y--
}else if sum==target {
return sum
}
}
}
return result
}