[LeetCode解題攻略] 15. 3Sum

更新於 發佈於 閱讀時間約 9 分鐘

題目描述

給定整數陣列nums,傳回所有三元組[nums[i], nums[j], nums[k]],使得i != j, i != k, j != k,且nums[i ] + nums[j] + nums[k] == 0。

請注意,解決方案集不得包含重複的三元組。

  1. 範例 1
    Input: nums = [-1, 0, 1, 2, -1, -4]
    Output: [[-1, -1, 2], [-1, 0, 1]]
    • 和為 0 的三元組為 [-1, -1, 2] 和 [-1, 0, 1]。
  2. 範例 2
    Input: nums = [0, 1, 1]
    Output: []
    • 唯一可能的三元組和不等於 0。
  3. 範例 3
    Input: nums = [0, 0, 0]
    Output: [0, 0, 0]
    • 唯一可能的三元組之和為 0。

解題思路

這題的核心是如何高效地找到所有符合條件的三元組,同時避免重複。以下是常見的解法:

  1. 暴力解法:使用三層迴圈遍歷所有三元組並檢查和是否為零。
  2. 排序 + 雙指針:利用排序後的性質,將問題轉換為類似 Two Sum 的雙指針解法。
  3. HashSet 儲存結果:用雜湊結構儲存已發現的三元組以去除重複的結果。

解法 1:暴力解法

思路

直接使用三層迴圈枚舉所有三元組,檢查每組數字的和是否為零。如果成立,將該三元組加入結果集。

實現 (Python)

class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
result = []
n = len(nums)

for i in range(n):
for j in range(i + 1, n):
for k in range(j + 1, n):
if nums[i] + nums[j] + nums[k] == 0:
triplet = sorted([nums[i], nums[j], nums[k]])
if triplet not in result:
result.append(triplet)

return result

時間與空間複雜度

  • 時間複雜度:O(n³),三層迴圈遍歷所有可能組合。
  • 空間複雜度:O(n),結果集中最多存儲所有三元組。

解法 2:排序 + 雙指針

思路

  1. 排序:先對數組進行升序排序,這樣可以有效避免重複並簡化搜索範圍。
  2. 固定一個數字,轉換為 Two Sum:遍歷每個數字作為固定的第一個數字,然後在剩下的數組中使用雙指針找到和為目標值(即 -固定數字)的兩個數。
  3. 跳過重複數字:為了避免重複,對固定數字和雙指針進行去重處理。

實現 (Python)

class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort() # 排序
result = []
n = len(nums)

for i in range(n):
# 避免固定數字重複
if i > 0 and nums[i] == nums[i - 1]:
continue

target = -nums[i] # 尋找和為 -nums[i] 的兩數
left, right = i + 1, n - 1

while left < right:
current_sum = nums[left] + nums[right]
if current_sum == target:
result.append([nums[i], nums[left], nums[right]])
left += 1
right -= 1
# 跳過重複數字
while left < right and nums[left] == nums[left - 1]:
left += 1
while left < right and nums[right] == nums[right + 1]:
right -= 1
elif current_sum < target:
left += 1 # 當前和小於目標,移動左指針
else:
right -= 1 # 當前和大於目標,移動右指針

return result

時間與空間複雜度

  • 時間複雜度:O(n²)
    • 排序的時間複雜度為 O(n log n),雙指針部分為 O(n²),所以總計 O(n²)。
  • 空間複雜度:O(1)
    • 除了返回結果外,僅需額外變數儲存指針與目標值。

解法 3:HashSet 儲存結果

思路

  1. 使用兩層迴圈,對於每個固定數字,將問題轉換為 Two Sum
  2. 用 HashSet 儲存已訪問過的數字,並檢查是否存在補數。
  3. 用另一個 HashSet 儲存已找到的三元組,以去除重複結果。

實現 (Python)

class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
result = set() # 使用 set 去除重複結果
n = len(nums)

for i in range(n):
target = -nums[i]
seen = set() # 儲存當前已訪問的數字
for j in range(i + 1, n):
complement = target - nums[j]
if complement in seen:
result.add((nums[i], nums[j], complement))
seen.add(nums[j])

return [list(triplet) for triplet in result]

時間與空間複雜度

  • 時間複雜度:O(n²)
    • 外層迴圈為 O(n),內層使用 HashSet 檢查補數的操作為 O(n),總計 O(n²)。
  • 空間複雜度:O(n)
    • 使用了額外的 HashSet 儲存已訪問的數字。

總結

最推薦的解法是 排序 + 雙指針法,因為它的時間複雜度較低,且能在不額外消耗太多空間的情況下解決問題。如果希望更靈活地處理重複三元組,則可以選擇 HashSet 儲存結果 的方法。


留言
avatar-img
留言分享你的想法!
avatar-img
追極光的北極熊|軟體工程師的小天地
7會員
132內容數
歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
2025/04/04
給定一個非負整數陣列 nums,其中 nums[i] 代表你在索引 i 處最多可以向右跳幾步。 請判斷是否能夠從索引 0 跳到最後一個索引。
2025/04/04
給定一個非負整數陣列 nums,其中 nums[i] 代表你在索引 i 處最多可以向右跳幾步。 請判斷是否能夠從索引 0 跳到最後一個索引。
2025/03/28
給定一個 m x n 的矩陣 matrix,請按照 螺旋順序(spiral order) 返回矩陣中的所有元素。
2025/03/28
給定一個 m x n 的矩陣 matrix,請按照 螺旋順序(spiral order) 返回矩陣中的所有元素。
2025/03/20
這道題是 LeetCode 的經典題之一,要求我們找出 一個子陣列,使其和最大,並返回這個最大和的數值。
2025/03/20
這道題是 LeetCode 的經典題之一,要求我們找出 一個子陣列,使其和最大,並返回這個最大和的數值。
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
題目敘述 Subarray Sums Divisible by K 給定一個整數陣列,請計算有幾個區間和能夠整除k的連續區間? 測試範例 Input: nums = [4,5,0,-2,-3,1], k = 5 Output: 7
Thumbnail
題目敘述 Subarray Sums Divisible by K 給定一個整數陣列,請計算有幾個區間和能夠整除k的連續區間? 測試範例 Input: nums = [4,5,0,-2,-3,1], k = 5 Output: 7
Thumbnail
Continuous Subarray Sum 給定一個整數陣列,請問是否存在一段區間和能夠整除k的連續區間,而且區間長度≥2? 如果存在,返回True。 無果無解,返回False。 例如[2,5,3,1,8,6], k = 6, 其中[3,1,8]是區間和能夠整除6的連續區間,而且區間長度≥2
Thumbnail
Continuous Subarray Sum 給定一個整數陣列,請問是否存在一段區間和能夠整除k的連續區間,而且區間長度≥2? 如果存在,返回True。 無果無解,返回False。 例如[2,5,3,1,8,6], k = 6, 其中[3,1,8]是區間和能夠整除6的連續區間,而且區間長度≥2
Thumbnail
題目敘述 題目會給定我們一個輸入陣列nums,要求我們掃描美個陣列元素nums[i],計算除了nums[i]以外的陣列元素連乘積。 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4] Output: [24,12,8,6] nums[0] 以
Thumbnail
題目敘述 題目會給定我們一個輸入陣列nums,要求我們掃描美個陣列元素nums[i],計算除了nums[i]以外的陣列元素連乘積。 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4] Output: [24,12,8,6] nums[0] 以
Thumbnail
題目敘述 題目會給我們一個參數k 和 目標值n。 請問我們從1~9內挑k個相異的數字,使得他們的總和為n 的組合數有多少? 挑選時,每個數字必須相異,而且每個數字只能選一次。 題目的原文敘述 測試範例 Example 1: Input: k = 3, n = 7 Output: [
Thumbnail
題目敘述 題目會給我們一個參數k 和 目標值n。 請問我們從1~9內挑k個相異的數字,使得他們的總和為n 的組合數有多少? 挑選時,每個數字必須相異,而且每個數字只能選一次。 題目的原文敘述 測試範例 Example 1: Input: k = 3, n = 7 Output: [
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,和一個指定的k值。 請問,在輸入陣列nums中,有幾個子陣列的元素總合恰好為k ? 例如: nums = [1,2,3], k = 3 則有兩個子陣列的元素總合為3,分別是[1,2] 和 [3] 如果是第一次聽到或接觸前綴和prefix的同學
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,和一個指定的k值。 請問,在輸入陣列nums中,有幾個子陣列的元素總合恰好為k ? 例如: nums = [1,2,3], k = 3 則有兩個子陣列的元素總合為3,分別是[1,2] 和 [3] 如果是第一次聽到或接觸前綴和prefix的同學
Thumbnail
正確答案居然有無限多組!找到任何一種就算通過,這是怎麼回事?
Thumbnail
正確答案居然有無限多組!找到任何一種就算通過,這是怎麼回事?
Thumbnail
題目會給定我們一個陣列,並且定義了一種三角形合併的操作。 當下這一排相鄰的兩項相加,對mod 10取餘數,會成為下一排的對應項,一直反覆操作,直到剩下一個元素為止。 要求我們返回最後一層的答案。 測試範例: Example 1: Input: nums = [1,2,
Thumbnail
題目會給定我們一個陣列,並且定義了一種三角形合併的操作。 當下這一排相鄰的兩項相加,對mod 10取餘數,會成為下一排的對應項,一直反覆操作,直到剩下一個元素為止。 要求我們返回最後一層的答案。 測試範例: Example 1: Input: nums = [1,2,
Thumbnail
題目:建立一個函數,該函數返回給定最小 4 個正整數的數組的兩個最低正數的總和。不會傳入浮點數或非正整數。例如,當一個數組像 [19, 5, 42, 2, 77], 輸出應該是 7。 [10, 343445353, 3453445, 3453545353453] 應該回來 3453
Thumbnail
題目:建立一個函數,該函數返回給定最小 4 個正整數的數組的兩個最低正數的總和。不會傳入浮點數或非正整數。例如,當一個數組像 [19, 5, 42, 2, 77], 輸出應該是 7。 [10, 343445353, 3453445, 3453545353453] 應該回來 3453
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News