LeetCode15 三數之和

2021-09-11 01:18:55 字數 3595 閱讀 7921

給定乙個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重複的三元組。

注意:答案中不可以包含重複的三元組。

例如, 給定陣列 nums = [-1, 0, 1, 2, -1, -4],

滿足要求的三元組集合為:

[

[-1, 0, 1],

[-1, -1, 2]

]

1、三重迴圈

雙重迴圈行不通,其實從組合數量出發,因為組合個數是n

3n^3

n3這個數量級,要遍歷所有的組合,時間複雜度應該也在o(n

3)o(n^3)

o(n3

)的樣子,使用三重迴圈應該是最佳的方法:

(1)第一重迴圈:left(取值範圍:0−n

−30-n-3

0−n−3)

(2)第二重迴圈:middle(取值範圍:1−n

−21-n-2

1−n−2)

(3)第三重迴圈:right(取值範圍:2−n

−12-n-1

2−n−1)

2、排序之後

等等,之前的結論都是建立在陣列是無序的情況下,事實上,對陣列排序的時間複雜度也僅僅是o(n

logn

)o(nlogn)

o(nlog

n),如果使用排序後的陣列能否大幅減少查詢時間呢?

每次將三個數之和(sum

=lef

t+mi

ddle

+rig

htsum=left+middle+right

sum=le

ft+m

iddl

e+ri

ght)與0比較:

(1)比0大則移動middle或者left

(2)比0小則移動middle或者right

(3)等於0,則儲存下來,然後???

這個方法也有很多問題,每次的移動,有兩個選擇,但是這兩個選擇並不是等價的

比如說當:

s um

>

0sum>0

sum>

0時,移動middle好呢還是移動right好?

還有當出現0的時候,為了尋找下乙個零,該怎麼移動?

3、分而治之

聯想之前兩數之和,三數之和的問題能否轉為兩數之和呢?

答案是肯定的。假設三個數為:i,j,k。對於兩數之和的target,這裡要求:target=-i

然後遍歷整個陣列,時間複雜度應該是:o(n

2)o(n^2)

o(n2

)最終我採用了這個方案,但是還是有些問題:

(1)因為陣列中可能存在重複的數,此時會有兩個一樣的target,返回的vector也是一樣的

(2)多對多的問題:

例如:i+j+k=0

對i來說,還有:

i+j1+k1=0

i+j2+k2=0

…i+jn+kn=0

對j來說,還有:

i1+j+k1=0

i2+j+k2=0

…in+j+kn=0

同理,k也有這種可能

但是之前的兩數之和的程式是假定,只有乙個解

1、嘗試-集合去重

接下來給出解決上述問題的方案:

(1)使用set來儲存陣列中的數,這樣可以達到去重的目的

(2)使用set來儲存得到的向量,且必須保持向量中的相對位置不變,這樣也可以去除重複的向量

很遺憾,這個想法是錯誤的,比如:[-1,0,1,-1]

第一次將[-1,0,1]放入集合,第二次還是會將[0,1,-1]也放進集合裡面

再比如:[-1,0,1,-1,0]這樣的資料

第一次將-1所在的所有向量選出來時,就已經重複了:

[-1,0,1]

[-1,1,0]

因此,集合沒有辦法對向量去重

實際上去重失敗的原因是:無法通過相對位置來決定唯一向量。所以,只要事先進行排序,就能解決這個問題:

c++**:

class solution 

};

執行效率:

港真,我都不想上圖了

更讓我震驚的是使用記憶體

短短50行的**用了600多mb的記憶體,這是咋回事???????

更新:這麼慢應該不是雜湊表的問題,我覺得是因為不必要的操作太多了,而且使用這種方法找兩數之和,不如雙指標來的快,實際上這個**已經是顯式的三重迴圈了

主要的思想還是分而治之,但是在解決兩數之和的問題時,不採用雜湊表,使用雙指標,看看速度能否更快一點

c++**:

class solution 	

if (nums[n] + nums[i] + nums[j] < 0)

if (nums[n] + nums[i] + nums[j] == 0) }}

} return nums_vector;

}};

執行效率:

比之前的版本強了很多,但是還是比較慢

記憶體占用:

可見,還是佔了很大一部分的記憶體

仔細看看這段**,會發現很多地方寫的很冗餘

(1)冗餘1

if (nums_p1.count(nums[n]) == 0) 

修改為:

if (n > 0 && nums[n] == nums[n - 1])

使用set判定重複,實際由於已經排好序了,因此判定重複只用與前乙個元素比較即可

(2)冗餘2

對向量的重複操作,總是在不斷插入刪除

c++**:

class solution 

if (nums[i] + nums[j] < target)

if ( nums[i] + nums[j] == target) );

while (i + 1 < j && nums[i] == nums[i + 1])

i++;

while (j - 1 > i && nums[j] == nums[j - 1])

j--;

i++;}}

} return vector>(nums_vector.begin(), nums_vector.end());

}};

效率還是老樣子,沒什麼提公升。。。。。。。

看了排名靠前的幾個,思路差不多,不知道為啥那麼快

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