LeetCode 15 三數之和

2022-06-17 23:09:18 字數 4239 閱讀 7361

題目:

給你乙個包含 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:盛水最多的容器,但是這題沒有想到用這個,自己還是不夠靈活分析問題...

思路:

首先我們對陣列先排序一次,在排好序的陣列上,就很容判斷前後元素是否相當,這樣可以過濾掉重複的答案。

再定義三個指標,kij如下圖所示

指標i從左往右移動,且始終比k大一位,這樣就保證不會跟k重疊,

指標j從右往左移動,且始終比i大,這樣ij就不會重疊,即三個指標都不會重疊。

# 正式處理之前,先將陣列排序

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...