16.最接近的三个数之和
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
方法一
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
i = 0
diff = 999
for i in range(len(nums)):
if i == 0 or nums[i]>nums[i-1]:###从第二个元素开始,重复的元素跳过。
l = i+1
r = len(nums)-1
while l < r:
s = nums[i] + nums[l] +nums[r] - target
if abs(s) < abs(diff) : diff = s
if s == 0 :
return target
elif s>0:
r -=1
else :
l +=1
return diff+target
- float(‘inf’) = 正无穷
- 排序,遍历,双指针
- 排序是为了使用双指针,首先遍历得到索引 c,然后计算 c,左指针 i,右指针 j 对应数字之和,如果大于 target,j 向内移动,否则 i 向内移动
- i 的初始值不是 c + 1,是为了减少计算量,用二分法得到一个合理的初始值
bisect 函数其实是 bisect_right 函数的别名,后者还有个姊妹函数叫bisect_left。
bisect_left函数是新元素会被放置于它相等的元素的前面,而 bisect_right返回的则是跟它相等的元素之后的位置。
方法二
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums, r, end = sorted(nums), float('inf'), len(nums) - 1
for c in range(len(nums) - 2):
i, j = max(c + 1, bisect.bisect_left(nums, target - nums[end] - nums[c], c + 1, end) - 1), end
while r != target and i < j:
s = nums[c] + nums[i] + nums[j]
r, i, j = min(r, s, key=lambda x: abs(x - target)), i + (s < target), j - (s > target)
return r