相向双指针刷题笔记:统计和小于目标的下标对数目,有效三角形的个数,最接近的三数之和

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:有效三角形的个数

611. 有效三角形的个数 - 力扣(LeetCode)

  • 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:最接近的三数之和

16. 最接近的三数之和 - 力扣(LeetCode)

  • 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
    
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值