題目:
給你乙個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?請你找出所有滿足條件且不重複的三元組。
注意:答案中不可以包含重複的三元組。
示例:給定陣列 nums = [-1, 0, 1, 2, -1, -4],
滿足要求的三元組集合為:
[[-1, 0, 1],
[-1, -1, 2]
]思路:
首先想到的是按照位去依次相加,得到為0的元素就塞入陣列,直到找到所有組合情況,注意刪除重複元素。
方法一的邏輯測試有實現我預期的功能,但是測試用例的預期結果有些怪異。
輸入:[-1,0,1,2,-1,-4]
輸出:[[-1,0,1],[-1,2,-1],[0,1,-1]]
預期結果:[[-1,-1,2],[-1,0,1]]
這麼看起來,[-1,0,1]和[0,1,-1]也算相同,需要去重,在想了很久之後,終於寫出乙個按照我理解的思路的方法,不過超時了...q_q, 但是思路很美麗啊,哈哈哈。
方法一:
import copy
class solution(object):
def threesum(self, nums):
""":type nums: list[int]
:rtype: list[list[int]]
"""nums.sort() #從大到小排序,方便後面的去重
length = len(nums)
length_count = length*(length-1)*(length-2)/3/2 #定義array count,為cn^3階乘,用於存放三元和為0的陣列
count = 0 #空陣列count
temp_list = [ for _ in range(length_count)] #宣告定義階乘數量的二維陣列
for i in range(length):
j = i
while j+1元素為空的二維陣列index才塞入新元素。
break
k +=1
for v in range(len(temp_list)): #找到空陣列數量
if len(temp_list[v]) ==0:
count +=1
for i in range(count): #刪除空陣列(因為空陣列只會在最後,所以用pop即可)
temp_list.pop()
list_arr = copy.copy(temp_list) #淺copy一次arr,用於下面的列舉遍歷,因為需要remove原arr中的相同元素,remove後不能改變其列舉值,所以需要copy乙份。
# print 'temp_list before = ',temp_list
for k,v in enumerate(list_arr): #刪除重複元素
while temp_list.count(v) >=2:
temp_list.remove(v)
print 'temp_list after = ',temp_list
return temp_list
方法二:方法一超時的原因是是在處理相同元素的時候裡面有四層迴圈......看著傻傻滴,那就換個思路去處理好了。既然我有用到排序和j k來定義第二位和第三位,我是不是應該用j ,k直接來獲取結果會更方便些。
參考題解王尼瑪的處理分享,思想就是雙指標,參考leecode 11:盛水最多的容器,但是這題沒有想到用這個,自己還是不夠靈活分析問題...
思路:
首先我們對陣列先排序一次,在排好序的陣列上,就很容判斷前後元素是否相當,這樣可以過濾掉重複的答案。
再定義三個指標,k
,i
,j
如下圖所示
指標i
從左往右移動,且始終比k
大一位,這樣就保證不會跟k
重疊,
指標j
從右往左移動,且始終比i
大,這樣i
和j
就不會重疊,即三個指標都不會重疊。
# 正式處理之前,先將陣列排序
nums = sorted(nums)
n = len(nums)
res =
# 假設陣列為[0,1,2,3,4,5,6,7,8,9,10]
# 第三個指標k最多到下標8位置,因為後面兩個位置需要留給另外兩個指標
for k in xrange(n-2):
# nums[k]>0,說明後面的元素肯定也大於0,最後結果肯定》0,故直接跳出
if nums[k]>0:
break
# 如果當前元素和前面乙個元素一樣,忽略重複元素
if k>0 and nums[k-1]==nums[k]:
continue
# 定義另外兩個指標 i 和 j
i,j = k+1,n-1
while i0:
j -= 1
while i方法三:
這個出自題解 xiaojing chen的解題思路,方法思想很簡單,由
a + b + c = 0
等價於a + b = -c
先對陣列進行排序, 再對排序後的陣列進行遍歷, 將每個元素的相反數作為key, 元素所在的位置作為value存入雜湊表中, 兩次遍歷陣列不斷檢查 a + b 之和是否存在於雜湊表中.
需要注意的點:
找到滿足條件的結果後, 需要將結果陣列序列化並存入令乙個雜湊表中, 以便對結果去重
首先在對 a,b 進行遍歷時, 如果當前元素與前乙個元素相同可直接跳過以優化效能 (思考: 後乙個元素能發現的結果一定會包含在前乙個元素的結果中). 另外, 僅在一層迴圈中加入此邏輯效能最佳. 該邏輯有效的前提是相同的元素需要連在一起, 所以需先對陣列進行排序
class solution(object):
def threesum(self, nums):
""":type nums: list[int]
:rtype: list[list[int]]
"""if len(nums) < 3:
return
'''先對陣列排序, 遍歷陣列遇到與前乙個元素相同的情況可直接跳過'''
nums.sort()
target_hash =
res =
res_hash = {}
for i, first in enumerate(nums):
'''當前元素與前乙個元素相同時, 可直接跳過以優化效能'''
if i > 0 and first == nums[i - 1]:
continue
for j, second in enumerate(nums[i + 1:]):
'''檢查兩數之和是否存在於雜湊表中'''
if first + second in target_hash:
target_index = target_hash[first + second]
if target_index == i or target_index == i + j + 1:
continue
'''將找到的結果存入另乙個雜湊表中, 避免包含重複結果'''
row = sorted([first, second, nums[target_index]])
key = ",".join([str(x) for x in row])
if key not in res_hash:
res_hash[key] = true
return res
LeetCode 15 三數之和
15.給定乙個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c 使得 a b c 0 找出所有滿足條件且不重複的三元組。注意 答案中不可以包含重複的三元組 方法一,個人解法正確,但是效率太低,時間複雜度o n 3 時間超時,無法提交至leetcode public s...
leetcode 15 三數之和
給定乙個包含 n 個整數的陣列nums,判斷nums中是否存在三個元素 a,b,c 使得 a b c 0 找出所有滿足條件且不重複的三元組。注意 答案中不可以包含重複的三元組。例如,給定陣列 nums 1,0,1,2,1,4 滿足要求的三元組集合為 1,0,1 1,1,2 class solutio...
leetcode15 三數之和
給定乙個包含 n 個整數的陣列nums,判斷nums中是否存在三個元素 a,b,c 使得 a b c 0 找出所有滿足條件且不重複的三元組。注意 答案中不可以包含重複的三元組。例如,給定陣列 nums 1,0,1,2,1,4 滿足要求的三元組集合為 1,0,1 1,1,2 先找兩數之和,然後再用un...