Skip to main content

Command Palette

Search for a command to run...

從LeetCode學演算法 - 3 Two Pointers

Published
•1 min read•View as Markdown

0015. 3Sum (Medium)

Question: Given an array nums of n integers, are there elements a, b, c in numssuch 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]
]

分析/解題: 題目要求從陣列中找出所有數組a, b, c,
使得三者相加為0,且不能重覆。

老話一句,請記得問有沒有排序XD~
以暴力法解本題的話,會發現每次取三個做組合,
顯然會得到一個O(N³)的時間複雜度的解。
那麼,嘗試排序看看能得到比較好的解嗎?
我們先拿題目的例子來看看,排序過後為
[-4, -1, -1, 0, 1, 2]
按順序排列會有什麼好處呢?
假設我們先固定最左邊的-4為a(因為要組合,我們可以令a<=b<=c),
那麼b+c必須等於4,這邊使用一個簡單的技巧,
先將b指定給-1的位置,c指定給2的位置,
兩者相加等於1,表示應該要取更大的值才有機會讓和等於4,
於是我們可以將b的位置向右移一格(這裡是重覆的所以可以跳過),
再次檢查和目標的大小比較。

那麼很容易可以發現一件事情:
當現在的值比目標值大時,表示應該要取更小的值,
只有將c往左移動才有可能達到。
反之,
當現在的值比目標值小時,表示應該要取更大的值,
只有將b往右移動才有可能達到。
因此,在固定a值的時候,只要將後面的數按照上面的方法,
一次移動一格的掃過一遍,就可以得到這個a值所可以成立的組合。

所以最終我們只要將a從0~len(nums)-3按順序跑過一遍,
將中間符合的組合都放進list中,即可得到答案。

重覆性的部分,只要記得檢查前一個和這一個用的數字是否相同即可避免。

上述的做法,由於使用到兩個指標(指針),並透過移動它們來達到掃描陣列的目的,我們通常稱這樣的解法為Two Pointer,是蠻常用的技巧。
時間複雜度的部分,排序的一般狀況是O(NlogN),
而a的長度是O(N),每次都要掃完其後的長度,掃描部分即為O(N²),
所以總體的時間複雜度為O(N²)。

Java:

這邊使用i, j, k標記,要用a, b, c也可XD
使用Arrays.asList可以將一串元素塞成ArrayList。

Python: Python的部分提供了另一個的思路,
這是由 RouRouKerr在討論區所提出的解法,這邊是改成Python3版本。
他的想法是,在固定第一個數v的狀況,那當其中一個數為x,
另一個數只能是-v-x(因為加總要等於0)。
故每次將對應的互補數加入到dict中,
我們只要從頭到尾檢查,即可得到所有的正確組合。
這個想法跟前面Two Sum的解法概念是一樣的。
(對應到Java版本的解法也附在註解處)

面試實際可能會遇到的問題: 「(Python)前面不檢查的話後面你怎麼處理重覆?」(用set)
「假設目標不是0的話?」(方法應該是一樣的)
「(Python)dictionary的部分使用set代替會比較快嗎?」(實測過會變慢XD)
「(Java)如果可以改變input/output的變數形態的話,你會希望改動什麼?」
(改output,因為輸出應該固定會是3元組的組合(長度必然是3),
那大可以使用List,用List>其實較不理想)

只要掌握了Two Pointers的概念,很多題目其實可以在排序後輕鬆解決,
但記得注意有些題目可以比O(NlogN)快的話,排序會提高時間複雜度歐!

從LeetCode學演算法,我們下次見囉,掰~

如果你/妳覺得這篇文章不錯,請給我5個拍手,並且給我5個Like。(點開SHOW EMBED!)
如果你/妳非常喜歡這篇文章,可以按著拍手直到50下。
也請記得「Follow」我,隨時收看最新的文章。

More from this blog

是的,估計是需要針對留言點reply才會通知,

是的,估計是需要針對留言點reply才會通知, 我前一個留言說明是回在文章底下,它可能沒有被Medium視為同一串留言的回應, 所以最近我嘗試點reply在您前面的留言留了一份同樣的內容, 看來需要這樣才會通知到。 不好意思,我以後會再注意表達的方式避免有不同解讀造成誤會。 同時再次跟所有讀者說明,個人除非是特殊狀況需求, 否則不會沒事點開任何人的github,甚或對coding style進行評論; 因此,當回應或文章中提到任何推薦使用的工具, 或可以協助改善生產力的東東, 基本都是筆者個人覺...

Apr 4, 20251 min read

(限時)活動分享-Bybit Lauchpool PIRATE

白挖的加密貨幣,不香嗎? 寫在前面:(基礎+進階+面試篇)從 LeetCode 學演算法 + 面試成功指南 (3990元 長期有效) https://bit.ly/lc2022all 容筆者工商一下,「從Leetcode學演算法|進階篇」這次選了40道難度加深的LeetCode題目,同樣也會細部解說對應的技巧及須要掌握的演算法!同時這次購買進階篇的話,額外還加贈「從Leetcode學演算法|面試篇」!當中包含了面試準備須知分享,及訪談國內外不同經驗的工程師,讓你不論是想走前端/後端/一般軟工或者...

Jun 16, 20241 min read
(限時)活動分享-Bybit Lauchpool PIRATE
跟

跟著Desolve學程式

227 posts