[英]Leetcode question '3Sum' algorithm exceeds time limit, looking for improvement
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0?给定一个包含 n 个整数的数组 nums,在 nums 中是否存在元素 a、b、c 使得 a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.在数组中找到所有唯一的三元组,其总和为零。
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
My soulution is working well but it appears that it may be too slow.我的解决方案运行良好,但似乎它可能太慢了。 Is there a way to improve my codes without changing it significantly?有没有办法在不显着改变代码的情况下改进我的代码?
This is a O(n^2) solution with some optimization tricks:这是一个具有一些优化技巧的 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]
First, you need a hash lookup to reduce your O(n^3) algorithm to O(n^2).首先,您需要一个 hash 查找来将您的 O(n^3) 算法减少到 O(n^2)。 This is the whole idea, and the rest are micro-optimizations:这就是整个想法,rest 是微优化:
I'd suggest:我建议:
for j in range(i+1, length):
This will save you len(nums)^2/2 steps and first if statement becomes redundant.这将为您节省 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)
To avoid unneeded calls to sorted
in the innermost loop.避免在最内层循环中对sorted
进行不必要的调用。
This is an optimized version, will pass through:这是一个优化版本,将通过:
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
The TLE is most likely for those instances that fall into these two whiles: TLE 最有可能适用于属于这两种情况的那些实例:
while lo < hi and nums[lo] == nums[lo + 1]:
while lo < hi and nums[lo] == nums[lo + 1]:
Your solution is the brute force one, and the slowest one.您的解决方案是蛮力解决方案,也是最慢的解决方案。 Better solutions can be:更好的解决方案可以是:
Assume you start from an element from array.假设您从数组中的一个元素开始。 Consider using a Set for finding next two numbers from remaining array.考虑使用 Set 从剩余数组中查找接下来的两个数字。
There is a 3rd better solution as well.还有第三个更好的解决方案。 See https://www.gyanblog.com/gyan/coding-interview/leetcode-three-sum/见https://www.gyanblog.com/gyan/coding-interview/leetcode-three-sum/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.