ps:笔记和代码按本人理解整理,重思路
【如果笔记对你有帮助,欢迎关注&点赞&收藏,收到正反馈会加快更新!谢谢支持!】
往期学习笔记:
相向双指针学习笔记(一):两数之和 II ,三数之和-CSDN博客
相向双指针学习笔记(二):盛最多水的容器,接雨水-CSDN博客
题目1:统计和小于目标的下标对数目
2824. 统计和小于目标的下标对数目 - 力扣(LeetCode)
- ⚠️注意:使用相向双指针之前,序列都要排序!
- 双指针移动过程:
- 重点注意当 nums[left] + nums[right] < right 时,有 right - left 个答案(有的一段right都满足条件),然后向右移动 left指针
- 代码:
class Solution: def countPairs(self, nums: List[int], target: int) -> int: nums.sort() ans = 0 left = 0 right = len(nums)-1 while left < right: if nums[left] + nums[right] < target: ans += right - left # 注意这里的数量 left += 1 else: right -= 1 return ans
题目2:有效三角形的个数
- 15. 三数之和 的变形
(三数之和详细题解见相向双指针学习笔记(一):两数之和 II ,三数之和-CSDN博客) - 固定最长边 or 最短边?
- 固定最长边:“nums[left]+nums[right]” 和 “最长边长度” 比较 → 相向双指针
- 固定最短边:“最短边长度+nums[left]” 和 “nums[right]”比较 → 同向双指针
- 代码(固定最长边):
class Solution: def triangleNumber(self, nums: List[int]) -> int: nums.sort() n = len(nums) ans = 0 for l in range(2, n): # 最长边从nums[2]开始 left = 0 right = l-1 while left < right: if nums[left] + nums[right] > nums[l]: ans += right - left right -= 1 else: left += 1 return ans
题目3:最接近的三数之和
- 15. 三数之和 的变形
- 拆解:
- ans 记录“最接近target的三数之和”
- 以固定最小值(nums[pre])为例
- 优化点1:如果遇到重复的最小值(即nums[pre-1] == nums[pre])直接跳过
- 优化点2:如果nums[pre]+nums[pre+1]+nums[pre+2] > target,看ans是否更新,然后直接终止遍历返回结果(因为后面不可能让三数之和更小)
- 优化点3:如果nums[pre]+nums[-1]+nums[-2] < target,看ans是否更新,然后跳过本轮到下一个固定最小值
- 代码:
class Solution: def threeSumClosest(self, nums: List[int], target: int) -> int: nums.sort() ans = inf n = len(nums) for pre in range(n-2): if pre>0 and nums[pre] == nums[pre-1]: continue s = nums[pre]+nums[pre+1]+nums[pre+2] if s > target: if s-target < abs(ans-target): ans = s break s = nums[pre]+nums[-1]+nums[-2] if s < target: if target-s < abs(ans-target): ans = s continue left = pre+1 right = n-1 while left < right: cur = nums[pre] + nums[left] + nums[right] if abs(cur-target) < abs(ans-target): ans = cur if cur < target: left += 1 else: right -= 1 return ans