三数之和问题
给定一个数组,求其中三个数相加的和为目标值,组合不可重复
# -*- coding: utf-8 -*-
"""
@author: Ove
Stay hungry, stay foolish.
"""
# =============================================================================
# 给定一个数组,求三个数相加为 0 的组合
# 组合不可重复
# =============================================================================
# =============================================================================
# 排除000的情况,三个数中必定有负数的存在
# 先对数组进行排序,负数在前
# 获取一个负数,取反作为另外两个数的和
# 另外两个数,则取第一个数后面子集中的数
#
# =============================================================================
class Solution:
def threeSum(self, nums):
result = []
nums_len = len(nums)
if nums_len < 3:
return result
l,r,dif = 0,0,0
# 对数组进行排序
nums.sort()
for i in range(nums_len - 2):
# 第一个数为负数,若所有负数都取完(值大于0),break
if nums[i] > 0:
break
# 值相同时,跳过
if i > 0 and nums[i-1] == nums[i]:
continue
l = i + 1
r = nums_len - 1
dif = -nums[i]
# 在剩余子集中搜索相加值为dif的组合
while(l < r):
if nums[l] + nums[r] == dif:
result.append([nums[i],nums[l],nums[r]])
while l < r and nums[l]==nums[l + 1]:
l += 1
while l < r and nums[r] == nums[r - 1]:
r -= 1
l += 1
r -= 1
elif nums[l] + nums[r] < dif:
l += 1
else:
r -= 1
return result
# =============================================================================
# 问题推广,若求三数之和为固定值
# 若value > 0 至少一正,对排序后的数从末尾取第一个值
# 若value <= 0 至少一负,与目标为0解法一致
# =============================================================================
def ThreeSum2Value(self,data,value):
if len(data) < 3:
return []
if value > 0 :
return self.positive(data,value)
elif value < 0 :
return self.negative(data,value)
else:
return self.negative(data,0)
#目标值大于 0 至少一正
def positive(self,data,value):
result = []
nums_len = len(nums)
l,r,dif = 0,0,0
# 对数组进行排序
nums.sort()
for i in range(nums_len-1,1,-1):
# 从正数,数小于 0 时跳出
if nums[i] < 0:
break
# 值相同时,跳过
if i < nums_len and nums[i-1] == nums[i]:
continue
l = 0
r = i - 1
dif = value - nums[i]
# 在剩余子集中搜索相加值为dif的组合
while(l < r):
if nums[l] + nums[r] == dif:
result.append([nums[l],nums[r],nums[i]])
while l < r and nums[l]==nums[l + 1]:
l += 1
while l < r and nums[r] == nums[r - 1]:
r -= 1
l += 1
r -= 1
elif nums[l] + nums[r] < dif:
l += 1
else:
r -= 1
return result
#目标值小于等于 0 至少一负
def negative(self,data,value):
result = []
nums_len = len(nums)
l,r,dif = 0,0,0
# 对数组进行排序
nums.sort()
for i in range(nums_len - 2):
# 第一个数为负数,数大于 0 时跳出
if nums[i] > 0:
break
# 值相同时,跳过
if i > 0 and nums[i-1] == nums[i]:
continue
l = i + 1
r = nums_len - 1
dif = value - nums[i]
# 在剩余子集中搜索相加值为dif的组合
while(l < r):
if nums[l] + nums[r] == dif:
result.append([nums[i],nums[l],nums[r]])
while l < r and nums[l]==nums[l + 1]:
l += 1
while l < r and nums[r] == nums[r - 1]:
r -= 1
l += 1
r -= 1
elif nums[l] + nums[r] < dif:
l += 1
else:
r -= 1
return result
if __name__ == '__main__':
nums = [-1, 0, 0, 0, 1, 2, -1, -4]
s = Solution()
# print(s.threeSum(nums))
print(s.ThreeSum2Value(nums,2))
pass