# 原创 : leetcode15-三数之和 # leetcode15-三数之和 > 题目详见:[https://leetcode-cn.com/problems/3sum/description/](https://leetcode-cn.com/problems/3sum/description/) > 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。 注意:答案中不可以包含重复的三元组。 ``` 例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ] ``` 这道题我遇到好几次了,B站后台开发工程师笔试题就考了这个。今天就来总结一下解决方案。
这道题并不难,正常人的第一反应肯定是三个循环,再简单不过了,可是时间复杂度是不是有点大。。。提交也不让通过是吧。
首先写好边界条件,数组小于三个元素就不满足条件: ``` result = [] nums_len = len(nums) if nums_len < 3: return result ``` 注意我们用的是Python语言,所以可以直接**先用内建函数`sort()`排序**,**方便操作。然后可以用一个for循环,两个指针遍历**,时间复杂度也就是 o ( n 2 ) o(n^2) o(n2),与之前的三循环减小了不少。了解了这些差不多就可以实现代码了。 ``` class Solution(object): def threeSum(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ result = list() nums_len = len(nums) if nums_len < 3: return result l, r, dif = 0, 0, 0 nums.sort() for i in range(nums_len - 2): if nums[i] > 0: break if i > 0 and nums[i - 1] == nums[i]: continue l = i + 1 r = nums_len - 1 dif = -nums[i] while l < r: if nums[l] + nums[r] == dif: result.append([nums[l], nums[r], nums[i]]) # 这两个while完全可以不要 while l < r and nums[l] == nums[l + 1]: l += 1 while l < r and nums[r] == nums[r - 1]: r -= 1 l += 1 r -= 1 elif nums[l] + nums[r] < dif: l += 1 else: r -= 1 return result ``` 另外,leetcode16题也是差不多这个意思: > 例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2). 思路一模一样,一个for,加上两个指针,时间复杂度为 O ( n 2 ) O(n^2) O(n2) ``` class Solution(object): def threeSumClosest(self, nums, target): """ :type nums: List[int] :type target: int :rtype: int """ # n = len(nums) # if n<3:return None # res = sum(nums[0:3]) # diff = abs(res - target) # for i in range(0,n-2): # for j in range(i+1,n-1): # for k in range(j+1,n): # tmp = nums[i]+nums[j]+nums[k] # if diff > abs(tmp - target): # diff = abs(tmp - target) # res = tmp # return res n = len(nums) if n<3:return None nums.sort() res = sum(nums[0:3]) diff = abs(res - target) for i in xrange(len(nums)-2): low = i+1 high = len(nums)-1 while low<high: tmp = nums[i]+nums[low]+nums[high] if abs(res-target) > abs(tmp-target):res = tmp elif target < tmp: high -= 1 else: low += 1 return res ```