三数之和
题目描述:
解题思路:
- 第一种:对于这道题,我们用的是排序 + 双指针的解法。开始我们有个比较好的思路,就是我们可以先对数组进行从小到大排序,然后我们容易发现,要使得三个数相加为0,第一个数必须要是小于等于零,如果大于零了,那后面的数字也是大于零的,这样相加肯定是不可能等于0的。所以我们只需要从小开始找,直到发现第一个数开始大于零了,就可以返回这些三元组了。下一个就是我们在头尾设置双指针
Left
和Right
,然后找到满足条件的三元组放进新定义的数组dic
中。还有比较重要的点是去重,这里有两处去重,一处是第一个数,还有一处是双指针处,都要保证当前用的数字不能和前一个相同。
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
lens = len(nums)
dic = []
nums.sort()
if lens < 3:
return []
else:
for i in range(lens):
if nums[i] <= 0:
if i > 0 and nums[i] == nums[i-1]:
continue
Left = i + 1
Right = lens - 1
while Left < Right:
if nums[i] + nums[Left] == -nums[Right]:
dic.append([nums[i], nums[Left], nums[Right]])
while Left < Right and nums[Left] == nums[Left + 1]:
Left += 1
while Left < Right and nums[Right] == nums[Right - 1]:
Right -= 1
Left += 1
Right -= 1
elif nums[i] + nums[Left] < -nums[Right]:
Left += 1
else:
Right -= 1
else:
return dic
return dic
类似方法,减少代码量。
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
lens = len(nums)
nums.sort()
Res = []
for i in range(lens-2):
if nums[i] > 0:
break
if i > 0 and nums[i] == nums[i-1]:
continue
j = i + 1
h = lens - 1
while j < h:
if nums[i] + nums[j] == -nums[h]:
Res.append([nums[i], nums[j], nums[h]])
h -= 1
j += 1
while j < h and nums[j] == nums[j-1]:
j += 1
while j < h and nums[h] == nums[h+1]:
h -= 1
elif nums[i] + nums[j] > -nums[h]:
h -= 1
while j < h and nums[h] == nums[h+1]:
h -= 1
else:
j += 1
while j < h and nums[j] == nums[j-1]:
j += 1
return Res
- 第二种:我看了看一些大佬的解法,下面用哈希表法来解决这个问题。同理一开始也是先对数组进行排序, 遍历数组如果遇到与前一个元素相同的情况,就直接跳过。这里比较巧妙的就是,把三数之和问题简化成了两数之和问题,这里一开始就把每个元素的相反数都存入哈希表中,然后就只需要看两数之和是否在哈希表中即可。时间复杂度为O(n^2) 。
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
Res = []
nums.sort()
if len(nums) < 3:
return Res
target_hash = {-x: i for i, x in enumerate(nums)}
res_hash = {}
for i, Front in enumerate(nums):
if i > 0 and Front == nums[i - 1]:
continue
for j, Back in enumerate(nums[i + 1:]):
if Front + Back in target_hash:
target_index = target_hash[Front + Back]
if target_index == i or target_index == i + j + 1:
continue
dic = sorted([Front, Back, nums[target_index]])
key = ",".join([str(x) for x in dic])
if key not in res_hash:
Res.append(dic)
res_hash[key] = True
return Res
- 第三种:这个方法用到了一个
bisect
模块,用二分法来解决该问题就运行速度快了很多。(以后再补充)
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
Res = []
dic = {}
for a in nums:
dic[a] = dic.get(a, 0) + 1
nums = sorted(dic)
for b, temp in enumerate(nums):
if dic[temp] > 1:
if temp != 0:
if -temp * 2 in dic:
Res.append([temp, temp, -2 * temp])
else:
if dic[temp] > 2:
Res.append([0, 0, 0])
if temp < 0:
two_sum = -temp
left = bisect.bisect_left(nums, (two_sum - nums[-1]), b + 1)
for i in nums[left: bisect.bisect_right(nums, (two_sum // 2), left)]:
j = two_sum - i
if j != i and j in dic:
Res.append([temp, i, j])
return Res