15. 3Sum

15. 3Sum

Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != ji != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.

Notice that the solution set must not contain duplicate triplets.

Example 1:

Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Explanation: 
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.
The distinct triplets are [-1,0,1] and [-1,-1,2].
Notice that the order of the output and the order of the triplets does not matter.

Example 2:

Input: nums = [0,1,1]
Output: []
Explanation: The only possible triplet does not sum up to 0.

Example 3:

Input: nums = [0,0,0]
Output: [[0,0,0]]
Explanation: The only possible triplet sums up to 0.

Constraints:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

 

https://blog.csdn.net/qq_37821701/article/details/111772660

 

解法1:hash table + sort triplets
这解法T了,应该是T在遍历之前储存的pair那边。不过我个人感觉这种做法比较直观

class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
pairs = collections.defaultdict(list)
n = len(nums)
ans = set()

for i in range(n):
for j in range(i+1,n):
pairs[nums[i]+nums[j]].append((i,j))

for i in range(n):
if (0-nums[i]) not in pairs:
continue
for pair in pairs[0-nums[i]]:
if i != pair[0] and i!=pair[1]:
ans.add(tuple(sorted((nums[i],nums[pair[0]],nums[pair[1]]))))

return ans;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
下面两种解法参考Leetcode官方

解法2:双指针+排序
两个关键点:

排序来有效避免重复组合的出现
双指针求two sum减少时间复杂度
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
res = []
nums.sort()
n = len(nums)
for i in range(n):
# we will search three numbers start from index i. So if nums[i]>0 and the nums is sorted, not valid triplets will appear
if nums[i]>0:
break
# only use the first accounted number to avoid duplicates
if i==0 or nums[i-1]!=nums[i]:
# use two pointer to search for pairs for nums[i]
lo = i+1
hi = n-1
while lo<hi:
_sum = nums[i] + nums[lo] +nums[hi]
if _sum < 0:
lo += 1
elif _sum > 0:
hi -= 1
else:
res.append((nums[i],nums[lo],nums[hi]))
lo += 1
hi -= 1
# again, we need to avoid duplicates. But we only need to do it for lo or hi, because once one of them is changed, the other will change to
while lo<hi and nums[lo]==nums[lo-1]:
lo += 1
return res
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
解法3:hash table + 排序
外循环和避免重复组合的方法与解法2一致,只是two sum用hash table来作

class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
res = []
nums.sort()
n = len(nums)
for i in range(n):
# we will search three numbers start from index i. So if nums[i]>0 and the nums is sorted, not valid triplets will appear
if nums[i]>0:
break
# only use the first accounted number to avoid duplicates
if i==0 or nums[i-1]!=nums[i]:
# use hash table to search for pairs for nums[i]
# seen use to keep the second element that has appeared, so the we can search for the pairs in O(n) rather than O(n^2)
seen = {}
j = i+1
while j<n:
remain = -nums[i]-nums[j]
if remain in seen:
res.append((nums[i],nums[j],remain))
# again, we need to avoid duplicates,here we must compare nums[j+1] and nums[j] rather than nums[j-1] and nums[j] because j is initially set to i+1. we don’t move j when nums[j] happens to be equal to nums[i]
while j+1<n and nums[j+1]==nums[j]:
j += 1
seen[nums[j]] = True;
j += 1

return res

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        results = []
        nums.sort()
        n = len(nums)

        for i in range(n):
            if nums[i] > 0:
                break
            
            if i == 0 or nums[i-1] != nums[i]:
                low = i+1
                high = n-1
                print(low)
                print(high)
                while low < high:
                    # print("********************")
                    # print(low)
                    # print(high)
                    # print(i)
                    tmp_sum = nums[low] + nums[high] + nums[i]

                    if tmp_sum < 0:
                        low += 1
                    elif tmp_sum > 0:
                        high -= 1
                    else:
                        results.append((nums[i], nums[low], nums[high]))
                        low += 1
                        high -= 1

                        while low < high and nums[low] == nums[low - 1]:
                            low += 1
                print("----------------------")
        return results
                        
No Comments

Post A Comment