【LeetCode】15. 3Sum 解題報告(Python)
題目描述:
Given an array nums
of n integers, are there elements a, b, c in nums
such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4], A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
題目大意
在給定的陣列中判斷是否存在三個數的和是0,返回所有的組合,但是返回的組合中不能有重複。
解題方法
方法一:統計頻率+雙指標
我的做法和大多數人不一樣,我看了很多人的做法是對原陣列排序後進行的左右指標向中間合併。而我這個做法使用的是先進行次數統計、元素去重然後做的雙指標。
我的這個思路是在923. 3Sum With Multiplicity中使用的,同樣地兩重迴圈,然後查詢第三個值是否在給出的數字set中,然後判斷3個數字相同的有多少,可能存在三個都相同,兩個相同,三個都不同的情況,這個時候需要注意的是還需要對原來的陣列中該數字出現的次數進行判斷。另外題目說了防止同樣的組合多次返回,那麼我是用了一個笨方法就是用set儲存已經使用了的組合,這樣能判斷是否已經出現過。
時間複雜度是O(N^2),空間複雜度是O(N)。看似操作複雜,實際上還是超過了48%的提交。
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
count = collections.Counter(nums)
values = count.keys()
values.sort()
print(values)
N = len(values)
l, r = 0, N - 1
res = list()
visited = set()
for l in range(N):
for r in range(l, N):
t = 0 - values[l] - values[r]
if t in count:
if (t == 0 and count[t] >= 3) \
or (((t == values[l] and t != values[r]) or (t == values[r] and t != values[l])) and count[t] >= 2) \
or (l == r and values[l] != t and count[values[l]] >= 2) \
or (t != values[l] and t != values[r] and l != r):
curlist = sorted([values[l], t, values[r]])
finger = "#".join(map(str, curlist))
if finger not in visited:
res.append(curlist)
visited.add(finger)
return res
方法二:原陣列排序+雙指標
這個方法就是上面說的對原陣列排序的做法,這個做法思路比較簡單,對於排序後的陣列遍歷,對每個位置都從它的後一個元素和末尾一個元素向中間集中,如果和為0就新增到結果陣列中。這裡需要注意的地方是需要跳過相同的數字,因為同樣的數字組合只能出現一次嘛。也就是兩個while,注意判斷相等的條件:i是向前面判斷,j是向後面判斷。
這個方法不用使用set來儲存已經遍歷過的數字組合,因為對於原陣列來說每次向後遍歷的過程中,同樣的組合只能出現一次。
時間複雜度是O(N^2),空間複雜度是O(1)。程式碼很清晰簡短,實際上只超過了24%的提交。
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
N = len(nums)
nums.sort()
res = []
for t in range(N - 2):
if t > 0 and nums[t] == nums[t - 1]:
continue
i, j = t + 1, N - 1
while i < j:
_sum = nums[t] + nums[i] + nums[j]
if _sum == 0:
res.append([nums[t], nums[i], nums[j]])
i += 1
j -= 1
while i < j and nums[i] == nums[i - 1]:
i += 1
while i < j and nums[j] == nums[j + 1]:
j -= 1
elif _sum < 0:
i += 1
else:
j -= 1
return res
參考資料:
日期
2018 年 10 月 17 日 —— 今又重陽,戰地黃花分外香