版权声明:本文为博主原创文章,未经允许不得转载。 https://blog.csdn.net/wem603947175/article/details/82081843
15. 三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路分析:
1.要找到相加和为0的三个数,可用多重循环来做,这种方法的时间复杂度是O(n^3),空间复杂度为O(1).提交之后提示超出时间限制。
Python代码实现:
class Solution(object):
def threeSum(self, nums):
three = []
for i in range(0,len(nums)):
for j in range(i+1,len(nums)):
for k in range(j+1,len(nums)):
if nums[i]+nums[j]+nums[k]==0:
a = sorted([nums[i],nums[j],nums[k]])
if a not in three:
three.append(a)
return (three)
2.试一试去掉一层循环,改为双重循环。结果仍是超出时间限制。
class Solution(object):
def threeSum(self, nums):
three = [] #建立一个空列表存放三元组
nums = sorted(nums) #将数组排序
for i in range(0, len(nums)):
for j in range(i + 1, len(nums)):
a = -(nums[i] + nums[j])
if a in nums[j+1:]: #查找以后的数,防止之前的数重用
b = nums[j+1:].index(a)+j+1
if b > j:
c = sorted([nums[i], nums[j], nums[b]])
if c not in three: #重复的三元组不添加
three.append(c)
return three
3.百度了一下这道题,别人的思路是:先对数组排序,然后开始遍历,对于数组中的每一个元素,用两指针往中间夹,直到找出所有的解。
也可理解为先排序,从小到大选取第一个数,再在剩余区间左右夹击,找到符合条件的。时间复杂度为 O(n^2).
类似与二叉搜索,只是每次往中间进一位。
实现
class Solution(object):
def threeSum(self, nums):
three_list = [] # 存储结果列表
nums = sorted(nums) # 对nums列表进行排序,无返回值,排序直接改变nums顺序
for i in range(len(nums)): # 如果排序后第一个数都大于0,则跳出循环,不可能有为0的三数之和
if nums[i] > 0:
break
if i > 0 and nums[i] == nums[i-1]: # 排序后相邻两数如果相等,则跳出当前循环继续下一次循环,相同的数只需要计算一次
continue
j = i + 1 # 记录i的下一个位置
k = len(nums) - 1 # 最后一个元素的位置
while j < k:
if nums[j] + nums[k] == -nums[i]: # 判断三数之和是否为0
three_list.append([nums[i], nums[j], nums[k]]) # 把结果加入数组中
while j < k and nums[j] == nums[j+1]: # 判断j相邻元素是否相等,有的话跳过这个
j += 1
while j < k and nums[k] == nums[k-1]: # 判断后面k的相邻元素是否相等,是的话跳过
k -= 1
j += 1 # 没有相等则j+1,k-1,缩小范围
k -= 1
elif nums[j] + nums[k] < -nums[i]: # 小于-nums[i]的话还能往后取
j += 1
else:
k -= 1
return three_list
之前的类似题:两数之和