三数之和-双指针
描述
给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。
数据范围:0 \le n \le 30000≤n≤3000,数组中各个元素值满足 |val | \le 100∣val∣≤100
空间复杂度:O(n^2)O(n2),时间复杂度 O(n^2)O(n2)
注意:
- 三元组(a、b、c)中的元素可以按任意顺序排列。
- 解集中不能包含重复的三元组。
示例1
输入:
[-10,0,10,20,-10,-40]
返回值:
[[-10,-10,20],[-10,0,10]]
示例2
输入:
[-2,0,1,1,2]
返回值:
[[-2,0,2],[-2,1,1]]
题目主要信息:
- 给定一个长度为nnn的数组,要找出其中所有满足相加等于0的三元组,即数组中所有三个相加为0的数集
- 三元组内部必须非降序排列,且三元组不能有重复
哈希表(推荐使用)
知识点1:哈希表
哈希表是一种根据关键码(key)直接访问值(value)的一种数据结构。而这种直接访问意味着只要知道key就能在O(1)O(1)O(1)时间内得到value,因此哈希表常用来统计频率、快速检验某个元素是否出现过等。
知识点2:双指针
双指针指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个指针(特殊情况甚至可以多个),两个指针或是同方向访问两个链表、或是同方向访问一个链表(快慢指针)、或是相反方向扫描(对撞指针),从而达到我们需要的目的。
思路:
直接找三个数字之和为某个数,太麻烦了,我们是不是可以拆分一下:如果找到了某个数aaa,要找到与之对应的另外两个数,三数之和为0,那岂不是只要找到另外两个数之和为−a-a−a?这就方便很多了。
因为三元组内部必须是有序的,因此可以优先对原数组排序,这样每次取到一个最小的数为aaa,只需要在后续数组中找到两个之和为−a-a−a就可以了,我们可以用双指针缩小区间,因为太后面的数字太大了,就不可能为−a-a−a,可以舍弃。
具体做法:
- step 1:排除边界特殊情况。
- step 2:既然三元组内部要求非降序排列,那我们先得把这个无序的数组搞有序了,使用sort函数优先对其排序。
- step 3:得到有序数组后,遍历该数组,对于每个遍历到的元素假设它是三元组中最小的一个,那么另外两个一定在后面。
- step 4:需要三个数相加为0,则另外两个数相加应该为上述第一个数的相反数,我们可以利用双指针在剩余的子数组中找有没有这样的数对。双指针指向剩余子数组的首尾,如果二者相加为目标值,那么可以记录,而且二者中间的数字相加可能还会有。
- step 5:如果二者相加大于目标值,说明右指针太大了,那就将其左移缩小,相反如果二者相加小于目标值,说明左指针太小了,将其右移扩大,直到两指针相遇,剩余子数组找完了。
注:对于三个数字都要判断是否相邻有重复的情况,要去重。
我的实现:class Solution: def threeSum(self , num: List[int]) -> List[List[int]]: num.sort() l = len(num) res = set() for i in range(l-2): j = i + 1 k = l -1 v = -num[i] while j < k: if num[j] + num[k] == v: res.add((num[i],num[j], num[k])) j +=1 k -=1 elif num[j] + num[k] > v: k -=1 else: j += 1 return list(res)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构