3Sum
这是我第一次参加 LeetCode (力扣) 的每月挑战题组,希望留下点笔记,大家可以参考和互相讨论。😃
第八天问:
给你一个有 n 个整数的数列 nums
,其中会不会有三个元素 a, b, c,相加之后为零?请在这数列中,找出所有能够相加为零 (组合不能重复) 的三元素数列。
题目与例子 (引用自LeetCode):
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note: The solution set must not contain duplicate triplets.
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
提示:
- 现在我们要找的是三个相加为零的数,但如果假设我们先固定一个数
x
,那就可以变成 2sum 问题。 - 在 2sum 问题上,如果假设我们先固定一个数
x
,那就需要扫一次整个数列找y = value - x
(value 是一个input parameter)。只是,能加速这算法吗? - 2sum 的第二个思路是:在不改变数列的前提下,或许能考虑用哈希表 (haspmap) 来加快计算?
解题思路:
2sum 题目容易算,是因为只有两个数,最简单粗暴的就是 double for-loop 迭代一下就完事了;但这个直接迭代是会超时报錯的。以下这段代因为时间复杂度太高,因为time limit exceeded又被打回了。
失败代码 (时间复杂度:O(n3 + n log n))
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
result = []
if len(nums) < 3:
return result
for i in range(len(nums)):
num1 = nums[i]
for j in range(i + 1, len(nums)):
num2 = nums[j]
k = j + 1
while k < len(nums):
num3 = nums[k]
if num2 + num3 == -1 * num1:
if sorted([num1, num2, num3]) not in result:
result.append(sorted([num1, num2, num3]))
k += 1
result.sort()
return result
想了一阵子,试了几遍,还是沒搞出来🤯。沒辦法,只好上网找资料。在 leetcode 的讨论区中,看到了一篇文章 (文章来源请看参考资料) 用了一个方法跟我上面有点类似,一开始也是从迭代整个数列 (for-loop) 入手,然后后面就不一样了:
- 第一个 if-clase 是用来跳过已经做过的迭代,避免重复计算 (因为条件
nums[i] == nums[i - 1]
代表现在的nums
值跟上一次一样,那上一個循环必定已包括这个循环会做的计算) beg
和end
分別是现值在 数列的位置的下一位数 和 数列最后一位数。- 最后,用 while-loop 做迭代,只要
nums[beg] + nums[end]
现值的负数,就可以加到答案列上。
这个方法好处是使用了 if-clause 和 while-loop 两个方法既可以減少时间复杂度,又能同步降低实际所需时间。
引用代码 (时间复杂度: O(n log n + n2))
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
n = len(nums)
result = []
for i in range(n):
if i > 0 and nums[i] == nums[i - 1]:
continue
target = -nums[i]
beg = i + 1
end = n - 1
while beg < end:
if nums[beg] + nums[end] < target:
beg += 1
elif nums[beg] + nums[end] > target:
end -= 1
else:
result.append((nums[i], nums[beg], nums[end]))
beg += 1
end -= 1
return set(result)
Reference/参考资料:
https://leetcode.com/problems/3sum/discuss/725581/Python-2-Pointers-O(n2)-solution-explained (代码引用来源)
https://www.cnblogs.com/grandyang/p/4481576.html