Python Leetcode问题&x27;3Sum';算法超出时间限制,正在寻求改进
给定一个由n个整数组成的数组nums,nums中是否有元素a、b、c使得a+b+c=0?查找数组中所有唯一的三元组,该数组的和为零Python Leetcode问题&x27;3Sum';算法超出时间限制,正在寻求改进,python,python-3.x,algorithm,Python,Python 3.x,Algorithm,给定一个由n个整数组成的数组nums,nums中是否有元素a、b、c使得a+b+c=0?查找数组中所有唯一的三元组,该数组的和为零 class Solution: def threeSum(self, nums): data = [] i = j = k =0 length = len(nums) for i in range(length): for j in range(length):
class Solution:
def threeSum(self, nums):
data = []
i = j = k =0
length = len(nums)
for i in range(length):
for j in range(length):
if j == i:
continue
for k in range(length):
if k == j or k == i:
continue
sorted_num = sorted([nums[i],nums[j],nums[k]])
if nums[i]+nums[j]+nums[k] == 0 and sorted_num not in data:
data.append(sorted_num)
return data
我的溶液效果很好,但似乎太慢了。
有没有一种方法可以在不显著更改代码的情况下改进代码?您的解决方案是蛮力方案,也是最慢的方案。 更好的解决方案可以是: 假设您从数组中的一个元素开始。考虑使用一个集合从剩余数组中查找下两个数字。< /P> 还有第三个更好的解决方案。请参见这是一个带有一些优化技巧的O(n^2)解决方案:
import itertools
class Solution:
def findsum(self, lookup: dict, target: int):
for u in lookup:
v = target - u
# reduce duplication, we may enforce v <= u
try:
m = lookup[v]
if u != v or m > 1:
yield u, v
except KeyError:
pass
def threeSum(self, nums: List[int]) -> List[List[int]]:
lookup = {}
triplets = set()
for x in nums:
for y, z in self.findsum(lookup, -x):
triplets.add(tuple(sorted([x, y, z])))
lookup[x] = lookup.get(x, 0) + 1
return [list(triplet) for triplet in triplets]
导入itertools
类解决方案:
def findsum(self,lookup:dict,target:int):
对于查找中的u:
v=目标-u
#减少重复,我们可以强制执行v 1:
产量u,v
除KeyError外:
通过
def threeSum(self,nums:List[int])->List[List[int]:
查找={}
三元组=集合()
对于NUM中的x:
对于self.findsum(查找,-x)中的y,z:
添加(元组(已排序([x,y,z]))
lookup[x]=lookup.get(x,0)+1
return[三元组中三元组的列表(三元组)]
首先,您需要一个散列查找来将O(n^3)算法减少到O(n^2)。这就是整个想法,其余都是微观优化:
- 查找表是随阵列上的扫描一起生成的,因此它是一次扫描
- 查找表索引以前看到的唯一项,因此它可以有效地处理重复项,通过使用它,我们可以将第二级循环的迭代次数保持在最小
- 我建议:
for j in range(i+1, length):
这将为您节省len(nums)^2/2个步骤,并且第一个if语句变得多余
sorted_num = sorted([nums[i],nums[j],nums[k]])
if nums[i]+nums[j]+nums[k] == 0 and sorted_num not in data:
sorted_num = sorted([nums[i],nums[j],nums[k]])
data.append(sorted_num)
为避免对最内层循环中排序的
进行不必要的调用。这是一个优化版本,将通过以下步骤:
from typing import List
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
unique_triplets = []
nums.sort()
for i in range(len(nums) - 2):
if i > 0 and nums[i] == nums[i - 1]:
continue
lo = i + 1
hi = len(nums) - 1
while lo < hi:
target_sum = nums[i] + nums[lo] + nums[hi]
if target_sum < 0:
lo += 1
if target_sum > 0:
hi -= 1
if target_sum == 0:
unique_triplets.append((nums[i], nums[lo], nums[hi]))
while lo < hi and nums[lo] == nums[lo + 1]:
lo += 1
while lo < hi and nums[hi] == nums[hi - 1]:
hi -= 1
lo += 1
hi -= 1
return unique_triplets
输入导入列表中的
类解决方案:
def threeSum(self,nums:List[int])->List[List[int]:
唯一的_三联体=[]
nums.sort()
对于范围内的i(len(nums)-2):
如果i>0且nums[i]==nums[i-1]:
持续
lo=i+1
hi=len(nums)-1
当lo0:
hi-=1
如果目标_sum==0:
唯一的三元组。追加((nums[i],nums[lo],nums[hi]))
而lo
TLE最有可能适用于以下两种情况:
而lo
而lo
工具书类
- 有关更多详细信息,请参阅,您可以在其中找到大量解释良好的公认解决方案,包括低复杂度算法和渐近/分析
您有i和j值。将所有内容存储在一个映射中并检查映射中是否存在(0-a-b),而不是再次迭代如何?如果您想要解决leetcode问题,请检查通道。这家伙解决了很多问题。否则,你可以打开讨论页面,在每个问题之后都可以使用该页面来优化解决方案。你的建议很容易理解,它帮助我加快了两倍,但仍然不够快,因为它仍然超过了时间限制。如果从listnums=list(set(nums)).sort()中删除重复的元素,我必须将O(n3)缩减为O(n2)。sort()
,我们可以避免三个额外的循环,使代码更短更清晰。