相向双指针学习笔记(一):两数之和 II ,三数之和

参考:两数之和 三数之和【基础算法精讲 01】_哔哩哔哩_bilibili

ps:笔记按本人理解整理,重思路

【如果笔记对你有帮助,欢迎关注&点赞&收藏,收到正反馈会加快更新!谢谢支持!】

题目1: 两数之和 II - 输入有序数组

167. 两数之和 II - 输入有序数组 - 力扣(LeetCode)

  • 思路:数组往左递增,往右递减;两数 → 双指针表示
  • 拆解:
    • 初始化:左指针 → 最小值(左端);右指针 → 最大值(右端)
    • numbers[left] + numbers[right] > target:  右指针向左移  → 两数之和变小
      numbers[left] + numbers[right] < target:  左指针向右移  → 两数之和变大
  • 代码:
    class Solution:
        def twoSum(self, numbers: List[int], target: int) -> List[int]:
            left = 0
            right = len(numbers) - 1
            while left < right:
                sum_ = numbers[left] + numbers[right]
                if sum_ == target:
                    return [left+1, right+1]
                elif sum_ > target:
                    right -= 1
                else:
                    left += 1
            

 题目2: 三数之和

15. 三数之和 - 力扣(LeetCode)

  • 思路:变有序数组 → 拆成两数之和问题 → 去重
  • 变化:要找出所有的三数之和,唯一解 → 所有解
  • 拆解:
    • 先sort成有序数组(有序时指针的移动才会有意义)
    • 三数之和 → 两数之和【A+B+C=0,固定A → B+C=-A(其中C>B>A,避免重复)】
      • 去重1:固定A时,重复的A只算一次
      • 【变化】算两数之和时要找出所有解:sum_ == target 时,左指针右移,右指针左移,并且跳过重复数字(去重2)
  • 代码:
    class Solution:
        def threeSum(self, nums: List[int]) -> List[List[int]]:
            result = []
            nums = sorted(nums)
            for i in range(len(nums)-2): 
                # 注释中 A=nums[i]
                if i > 0 and nums[i] == nums[i-1]:   # 固定A时的重复情况
                    continue
                if nums[i] > 0:   # 因为 C>B>A>0,三数之和不可能为0,直接结束
                    return result
                
                # 开始两数之和
                left = i+1
                right = len(nums)-1
                while left < right:
                    sum_ = nums[i]+nums[left]+nums[right]
                    if sum_ > 0:
                        right -= 1
                    elif sum_ < 0:
                        left += 1
                    else:
                        result.append([nums[i], nums[left], nums[right]])
                        # 因为这题可能有多个答案,要找出所有答案
                        # 找到一个解之后怎么找下一个解:跳过重复数字 → 左右指针同时右移和左移
                        while left < right and nums[left] == nums[left+1]: # 跳过重复数字
                            left += 1
                        while left < right and nums[left] == nums[right-1]:  # 跳过重复数字
                            right -= 1
                        left += 1    
                        right -= 1
                        
            return result
    

往期笔记:

二分查找学习笔记(一):在排序数组中查找元素的第一个和最后一个位置-CSDN博客

二分查找学习笔记(二):正整数和负整数的最大计数,咒语和药水的成功对数,H 指数 II-CSDN博客

二分查找学习笔记(三):寻找峰值,寻找峰值II-CSDN博客

二分查找学习笔记(四):寻找旋转排序数组中的最小值I & II,搜索旋转排序数组-CSDN博客

区间DP学习笔记:最长回文子序列,多边形三角剖分的最低得分-CSDN博客

状态机DP学习笔记-CSDN博客

树形DP学习笔记(一):树的路径问题-CSDN博客

树形DP学习笔记(二):打家劫舍III & 监控二叉树-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值