178 lines
4.2 KiB
Markdown
178 lines
4.2 KiB
Markdown
# 原创
|
||
: 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站后台开发工程师笔试题就考了这个。今天就来总结一下解决方案。<br/> 这道题并不难,正常人的第一反应肯定是三个循环,再简单不过了,可是时间复杂度是不是有点大。。。提交也不让通过是吧。<br/> 首先写好边界条件,数组小于三个元素就不满足条件:
|
||
|
||
```
|
||
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
|
||
|
||
```
|