给定一个包括 n 个整数的数组 nums
和 一个目标值 target
。找出 nums
中的三个整数,使得它们的和与 target
最接近。返回这三个数的和。假定每组输入只存在唯一答案。
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1. 与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
首先审题:1.一定需要三个数,也就是说我们需要三个指针指向这三个数。
2.这三个数的和可能等于也可能不等于目标
思路:这道题其实与上一道求三个数比较像。我们都需要设置三个指针去遍历这个数组。只不过目前我的代码可以优化,因为我不必每次都储存每次的和,我只需要最接近的和。并且我需要跳过重复的项去更快地遍历。贴上beat14的原代码和优化过的代码
class Solution:#比较慢
def threeSumClosest(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
nums.sort()
finalans = [nums[0] + nums[1] + nums[2]]
if nums[0] + nums[1] + nums[2] > target:
return finalans[0]
for i in range(len(nums)):
if nums[i]>0 and nums[i] > target :
break
if i > 0 and nums[i] == nums[i - 1]:
continue
j = i + 1
k = len(nums) - 1
while j < k:
ans = nums[i] + nums[j] + nums[k]
if ans == target:
return target
if ans not in finalans:
finalans.append(ans)
if ans > target:
k -= 1
while j < k - 1 and nums[k] == nums[k-1]: k-=1
else:
j += 1
while j < k - 1 and nums[j] == nums[j+1]: j+=1
return sorted(finalans, key=lambda x: abs(x - target))[0]
这套改良版击败了89, 主要改动为:1.只储存当前与target最接近的和
2.同时与其他博客不太一样的是采用了避免重复的步骤去跳过一些东西,加快了很多很多。
class Solution:#改良版
def threeSumClosest(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
result = sum(nums[:3])
if result == target:
return result
minDiff = abs(target - result)
nums.sort()
for i in range(len(nums)-2):
if i > 0 and nums[i] == nums[i-1]:
continue
j = i + 1
k = len(nums) - 1
while j < k:
ans = nums[i] + nums[j] + nums[k]
if ans == target:
return ans
if abs(target - ans) < minDiff:
result = ans
minDiff = abs(target - ans)
if ans > target:
k -= 1
while j < k - 1 and nums[k] == nums[k-1]: k-=1
else:
j += 1
while j < k - 1 and nums[j] == nums[j+1]: j+=1
return result
总结:1.求最优解有时可以只保存当前最优解,然后不断去更新。
2.排序之后的数组更易处理
3.重复数字能跳过,因为第一个相等数已经算完了你接下来可能要算的一些组合情况