来自leetcode
1.三数之和
题目要求
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
思路
首先考虑的是得到所有的三数和为0的集合, 最简单的思路就是遍历数组来完成。
然后是要解决重复的问题,考虑的是在将一个满足条件的三数和写入列表前先将其排序,再与列表中每个三数和进行比较,如何没有重复的再将其写入结果列表。思路上似乎是可行的,但是会超出时间限制,毕竟时间复杂度有点高。
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
#三个指针
length = len(nums)
result = []
for i in range(length-2):
for j in range(i+1,length):
for k in range(j+1,length):
if nums[i] + nums[j] + nums[k] == 0:
san = [nums[i],nums[j],nums[k]]
san.sort()
if not result.count(san):
result.append(san)
return result
然后对程序进行了改进,变成了先取两个数再查找列表中是否有一个数为两数和的相反数。但是效果并不明显。。。因为还是有去找这个数还是需要循环。。。
受算法哥启发,可以采用双指针来完成。
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
#三个指针
nums.sort()
length = len(nums)
result = []
i =0
left = i+1
right = length-1
while i < length-2 :
if nums[i] > 0 :
break
if nums[i] == -(nums[left]+nums[right]):
san = [nums[i],nums[left],nums[right]]
if not result.count(san):
result.append(san)
left += 1
right -= 1
while nums[left] == nums[left-1] and left < right:
left +=1
while nums[right] == nums[right+1] and left < right:
right -=1
elif (nums[left]+nums[right]) > -nums[i]:
right -= 1
elif (nums[left]+nums[right]) < -nums[i]:
left += 1
if left >= right:
i += 1
left = i+1
right = length-1
return result
写的步履维艰。。。虽然通过了,但是性能稀烂。略微优化了一下并附上官方的解法
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
#三个指针
nums.sort()
length = len(nums)
result = []
i =0
left = i+1
right = length-1
while i < length-2 :
if nums[i] > 0 :
break
if nums[i] == -(nums[left]+nums[right]):
result.append([nums[i],nums[left],nums[right]])
left += 1
right -= 1
while nums[left] == nums[left-1] and left < right:
left +=1
while nums[right] == nums[right+1] and left < right:
right -=1
elif (nums[left]+nums[right]) > -nums[i]:
right -= 1
elif (nums[left]+nums[right]) < -nums[i]:
left += 1
if left >= right:
i += 1
while i < length and nums[i] == nums[i-1]:
i +=1
left = i+1
right = length-1
return result
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
nums.sort()
ans = list()
# 枚举 a
for first in range(n):
# 需要和上一次枚举的数不相同
if first > 0 and nums[first] == nums[first - 1]:
continue
# c 对应的指针初始指向数组的最右端
third = n - 1
target = -nums[first]
# 枚举 b
for second in range(first + 1, n):
# 需要和上一次枚举的数不相同
if second > first + 1 and nums[second] == nums[second - 1]:
continue
# 需要保证 b 的指针在 c 的指针的左侧
while second < third and nums[second] + nums[third] > target:
third -= 1
# 如果指针重合,随着 b 后续的增加
# 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
if second == third:
break
if nums[second] + nums[third] == target:
ans.append([nums[first], nums[second], nums[third]])
return ans
文章介绍了LeetCode中的一个经典问题——找到数组中所有和为0的不重复三元组。最初的暴力遍历方法由于时间复杂度过高无法满足需求,随后通过使用双指针优化算法,减少了时间复杂度,实现了有效解决方案。经过不断优化,最终的代码通过了测试,但性能仍有提升空间。

被折叠的 条评论
为什么被折叠?



