15.三数之和
题目
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解思路
1>源代码
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
ans = []
for a in range(len(nums)):
if(a>0 and nums[a] == nums[a-1]):
continue
target = 0 - nums[a]
c = len(nums) - 1
for b in range(a+1, len(nums)):
if(b>a+1 and nums[b] == nums[b-1]):
continue
while(b<c and nums[b]+nums[c] > target):
c -= 1
if(b==c):
break
if(nums[b] + nums[c] == target):
ans.append([nums[a], nums[b], nums[c]])
return ans
2>算法介绍
本题其实和LeetCode——0001.两数之和有些相似,不同的是本题变为了三数之和。根据这个思路,我们可以将本题变成多个两数之和的形式。
但是,如果我们写三重循环,采用暴力遍历的方法就显得太过笨拙了。所以这道题我们换个方法,也是为了弥补一下两数之和那道题偷过的懒,采用双指针。
首先将列表排序,虽然排序会对时间复杂度造成影响,但是本题要想获得较好的性能,必须要进行排序。排序过后的列表我们维护三个指针 a b c 。由于数组是有序的,故当a指向nums[a]时,b不需要在之前的元素中进行遍历,只需要在nums[a+1:]进行操作。同时我们将target设置为0 - nums[a],这就相当于把这道题转化成了多个两数之和的形式。
在这里的两数之和我们也做一个简化,由于列表有序,所以我们的c指针从列表尾部开始,如果发现nums[b] + nums[c] <= target,则不需要继续遍历。
编写完这些后我们需要注意边界条件,由于题目要求我们的返回值不能存在重复的情况,所以在遍历的时候应去掉重复元素。另外,当b和c所指向的值相等的时候,b继续递增就没有意义了。
这道题总的来说思路比较简单,但是需要格外注意的就是结果如何去重以及各种边界条件。