leetcode刷题记--> 15题解法(python解析)
题目定义
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
来源:力扣(LeetCode)
链接: leetcode_15题.
解题
本次使用4种方法,在leetcode上还有更多的方法,只能说真牛逼,真聪明。
1. 暴力解法
使用暴力的方法进行搜索,先定住两个数,然后用0减去前两个数,看有没有值,如果有,添加进结果,然后使用numpy库进行去重
2. 定住两个数然后二分查找第三个
定住两个数,使用二分查找第三个数,然后使用内置库进行去重,注意set不能对多list去重,但是能对tuple进行去重
3. 定住一个数,然后二分查找后两个数
双下标法,极其巧妙,可以多看看
4. 使用python的内置函数
itertools.combinations (对数据进行自由组合,找出所有的组合)
frozenset
>>> frozenset((-1, 0, -1))
frozenset({-1, 0})
===================================================
实现
// An highlighted block
class Solution:
def threeSum(self, nums):
"""
# 1.暴力枚举法 n^3 超时了 严重超时
"""
if len(nums) < 3:
return []
list_end = []
for a in range(len(nums)):
for b in range(a + 1, len(nums)):
c = 0 - nums[a] - nums[b]
if c in nums[b + 1:]:
list_end.append(sorted([nums[a], nums[b], c]))
if len(list_end) < 1:
return []
import numpy as np
list_end = np.array(list_end)
list_end = np.unique(list_end, axis=0)
return list_end.tolist()
def threeSum_1(self, nums):
"""
# 二分查找 定住两个数 查第三个 n^2*logn
"""
nums.sort() # 先排序
ret = [] # 最终值
n = len(nums)
for i in range(0, n):
for j in range(i + 1, n): # 先定住两个
d = 0 - (nums[j] + nums[i]) # 找到第三个
l = 0 # 最左
r = n - 1 # 最右
p = -1
while l <= r:
m = (l + r) >> 1 # 取中值
if nums[m] == d:
p = m
break
elif nums[m] > d: # 如果 中间的值大于 d 这说明在左边
r = m - 1
elif nums[m] < d: # 如果 中间的值小于 d 这说明在右边
l = m + 1
if p != -1 and p != i and p != j:
ret.append( (nums[i], nums[j], nums[p]))
nn = len(ret)
for i in range(0, nn):
ret[i] = list(ret[i])
ret[i].sort()
ret[i] = tuple(ret[i])
ret = list(set(ret))
return ret
def threeSum_2(self, nums):
'''
# 同样是二分法进行查找 但是非常的巧妙 仔细理解一下
'''
nums.sort()
res = []
for i in range(len(nums)):
if i == 0 or nums[i] > nums[i - 1]: # 如果是刚开始 或者 排完序之后下一个数字大于前一个数字
l = i + 1 # 左
r = len(nums) - 1 #右
while l < r:
s = nums[i] + nums[l] + nums[r] # s= 当前数值 + 左边的数值 + 右边的数值
if s == 0:
res.append([nums[i], nums[l], nums[r]]) # 如果正好 等于 0
l += 1
r -= 1
while l < r and nums[l] == nums[l - 1]: # 执行的去重操作 如果左边的的数都相同就去重
l += 1
while r > l and nums[r] == nums[r + 1]: # 执行的去重操作 如果右边的的数都相同就去重
r -= 1
elif s > 0:
r -= 1
else:
l += 1
return res
def threeSum_3(self, nums):
import itertools
ts, bs = [i for i in set(list(itertools.combinations(nums, 3))) if sum(i) == 0], {} # 求出所有的组合 然后 set 去重 判断等于0 的加入ts
for i in ts:
'''
>>frozenset((-1, 0, -1))
frozenset({-1, 0})
输入 [-1, 0, 1, 2, -1, -4]
输出{frozenset({2, -1}): (-1, 2, -1), frozenset({0, 1, -1}): (-1, 0, 1)}
'''
bs.update({frozenset(i): i}) if frozenset(i) not in list(bs.keys()) else 0 # 将字典的key作为 frozenset存储
return list(bs.values())
print(Solution().threeSum_3( [-1, 0, 1, 2, -1, -4] ))