雙指標 模擬 leetcode 15 三數之和

2021-10-25 04:15:24 字數 2212 閱讀 9421

題目鏈結

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

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

示例:

給定陣列 nums =[-

1,0,

1,2,

-1,-

4],滿足要求的三元組集合為:[[

-1,0

,1],

[-1,

-1,2

]]

直接利用三層for迴圈列舉a、b、c,然後觀察a + b + c是否為0:

vectorint>>

threesum

(vector<

int>

& nums));

}}}}

return res;

}

這種做法在允許重複的情況下是沒有問題的,然而題目要求不能有重複。例如對樣例而言,上述**的輸出會多出乙個[0,1,-1],與[-1,0,1]重複。

那麼如何解決重複問題呢?

三數之和問題可以轉化為兩數之和問題。即:

a + b + c =0=

>

b + c =

-a

也就是找到兩數b、c的和為-a。因此,遍歷a可能的n種情況即可將問題轉化為相對簡單兩數之和問題:

//遍歷a

for(

int i =

0; i < n; i++

)}

觀察我們之前重複問題出現的原因。對於輸入:

[-1

,0,1

,2,-

1,-4

]

-1會被遍歷到兩次,因此帶來了重複問題。

一種解決方案是利用資料結構set,這裡我們採取另一種方法——排序。可以得到:

[-4

,-1,

-1,0

,1,2

]

//nums[i]與上乙個數nums[i - 1]相等則直接跳過

//i > 0是為了防止i - 1 < 0 導致陣列越界

if(i >

0&& nums[i]

== nums[i -1]

)

對於b、c的遍歷,可以簡單採用原來三層for迴圈的思路:

//遍歷b

for(

int j = i +

1; j < n; j++

)}

這樣做的時間複雜度是o(n2),有沒有更好的做法?

一種方式是將b、c改為一左一右的雙指標,即:

int k = n -1;

//遍歷b

for(

int j = i +

1; j < n; j++

)}

這樣做可以將遍歷b、c的複雜度降至o(n)。

合理性證明:

令b = nums[j], c = nums[k]。如果當前b + c != -a,要想使b + c = a,有兩種情況:

因此,在b + c < -a時使j右移,反之使k左移即可。這一雙指標的思想與盛水最多的容器十分相似。

class

solution

//target = -a

int target =

-nums[i]

;int k = n -1;

//遍歷b

for(

int j = i +

1; j < n; j++

)//如果b + c > -a,需要將c減小(即指標k左移))

while

(j < k && nums[j]

+ nums[k]

> target)

//左右指標相遇,退出

if(j == k)

if(nums[j]

+ nums[k]

== target));

}}}return res;}}

;

Leetcode15 三數之和(雙指標)

給定乙個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c 使得 a b c 0 找出所有滿足條件且不重複的三元組。注意 答案中不可以包含重複的三元組。例如,給定陣列 nums 1,0,1,2,1,4 滿足要求的三元組集合為 1,0,1 1,1,2 給定乙個包含 n 個...

leetcode15 三數之和 雙指標

給定乙個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c 使得 a b c 0 找出所有滿足條件且不重複的三元組。注意 答案中不可以包含重複的三元組。例如,給定陣列 nums 1,0,1,2,1,4 滿足要求的三元組集合為 1,0 1 1,1,2 本題的關鍵 去重!借...

LeetCode 15 三數之和

15.給定乙個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c 使得 a b c 0 找出所有滿足條件且不重複的三元組。注意 答案中不可以包含重複的三元組 方法一,個人解法正確,但是效率太低,時間複雜度o n 3 時間超時,無法提交至leetcode public s...