[LeetCode解題攻略] 39. Combination Sum

更新 發佈閱讀 4 分鐘

題目描述

給定一個無重複正整數數組 candidates 和一個目標值 target,找出所有可以使數字和為 target 的組合。

數組中的數字可以無限制重複選取,並且所有的組合需要是唯一的。


範例 1

輸入: candidates = [2,3,6,7], target = 7
輸出: [[2,2,3],[7]]
解釋:
2 + 2 + 3 = 7
7 = 7

範例 2

輸入: candidates = [2,3,5], target = 8
輸出: [[2,2,2,2],[2,3,3],[3,5]]

範例 3

輸入: candidates = [2], target = 1
輸出: []

條件限制

  • 所有數字(包括 target)均為正整數。
  • 數組中所有數字互不相同。
  • 答案中的組合可以按任意順序返回。

解題思路

這是一個經典的「組合問題」,解題的核心是利用回溯法(Backtracking)

回溯法的思路

  1. 將候選數組進行排序(有助於提前剪枝)。
  2. 使用遞迴探索所有可能的組合。
  3. 當當前組合的總和等於目標時,將組合加入答案。
  4. 如果總和超過目標值,則停止探索(剪枝)。

解法一:回溯法

思路

  1. 從候選數組中依次選取元素。
  2. 選取後,繼續探索包含該元素的子問題。
  3. 如果總和超過 target,停止探索(剪枝)。
  4. 當總和等於 target,將當前組合加入結果集。

程式碼

class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def backtrack(start, target, path):
if target == 0:
result.append(list(path)) # 找到一個組合
return
if target < 0:
return # 剪枝

for i in range(start, len(candidates)):
path.append(candidates[i]) # 選擇當前元素
backtrack(i, target - candidates[i], path) # 繼續探索
path.pop() # 撤銷選擇

result = []
candidates.sort() # 排序有助於剪枝
backtrack(0, target, [])
return result

時間與空間複雜度分析

  • 時間複雜度:O(2^t),t 是目標值 target,因為每個數字可能被多次選取並組成不同的組合。
  • 空間複雜度:O(t),遞迴的最大深度為 target

解法二:動態規劃

思路

  1. 將問題轉化為背包問題(完全背包)。
  2. 定義 dp[i] 為目標和為 i 的所有組合。
  3. 對於每個數字 num 和目標值 j,若 j >= num,則將 dp[j - num] 中的組合加上 num,形成新的組合,並存入 dp[j]

程式碼

class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
dp = [[] for _ in range(target + 1)]
dp[0] = [[]] # 和為 0 時的組合為空組合

for num in candidates:
for j in range(num, target + 1):
for comb in dp[j - num]:
dp[j].append(comb + [num])

return dp[target]

時間與空間複雜度分析

  • 時間複雜度:O(n * target),其中 n 是候選數組的大小,target 是目標值。
  • 空間複雜度:O(target),因為需要儲存每個和的組合。

結論

  1. 回溯法 是解決這類組合問題的直觀方法,適合初學者。
  2. 動態規劃 適合對性能要求較高的情況,但編碼複雜度較高。
  3. 根據具體問題的規模選擇合適的解法:當 candidates 較小時,使用回溯法;當目標值較大時,考慮動態規劃。
留言
avatar-img
留言分享你的想法!
avatar-img
追極光的北極熊|軟體工程師的小天地
12會員
163內容數
歡迎來到我的部落格!這裡記錄了軟體工程師的日常生活點滴,並分享程式設計與演算法的實用教學。無論你是初學者還是有經驗的開發者,都能在這裡找到深入淺出的技術解析與實戰技巧。此外,我也會分享工作中的心路歷程與學習心得,讓你不僅學到技術,更能瞭解軟體開發的實際應用與挑戰。希望透過這個平台,能與你共同成長,激發對技術的熱情!
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
透過蝦皮分潤計畫,輕鬆賺取零用金!本文分享5-6月實測心得,包含數據流程、實際收入、平臺優點及注意事項,並推薦高分潤商品,教你如何運用空閒時間創造被動收入。
Thumbnail
透過蝦皮分潤計畫,輕鬆賺取零用金!本文分享5-6月實測心得,包含數據流程、實際收入、平臺優點及注意事項,並推薦高分潤商品,教你如何運用空閒時間創造被動收入。
Thumbnail
單身的人有些會養寵物,而我養植物。畢竟寵物離世會傷心,植物沒養好再接再厲就好了~(笑)
Thumbnail
單身的人有些會養寵物,而我養植物。畢竟寵物離世會傷心,植物沒養好再接再厲就好了~(笑)
Thumbnail
不知你有沒有過這種經驗?衛生紙只剩最後一包、洗衣精倒不出來,或電池突然沒電。這次一次補貨,從電池、衛生紙到洗衣精,還順便分享使用心得。更棒的是,搭配蝦皮分潤計畫,愛用品不僅自己用得安心,分享給朋友還能賺回饋。立即使用推薦碼 X5Q344E,輕鬆上手,隨時隨地賺取分潤!
Thumbnail
不知你有沒有過這種經驗?衛生紙只剩最後一包、洗衣精倒不出來,或電池突然沒電。這次一次補貨,從電池、衛生紙到洗衣精,還順便分享使用心得。更棒的是,搭配蝦皮分潤計畫,愛用品不僅自己用得安心,分享給朋友還能賺回饋。立即使用推薦碼 X5Q344E,輕鬆上手,隨時隨地賺取分潤!
Thumbnail
身為一個典型的社畜,上班時間被會議、進度、KPI 塞得滿滿,下班後只想要找一個能夠安靜喘口氣的小角落。對我來說,畫畫就是那個屬於自己的小樹洞。無論是胡亂塗鴉,還是慢慢描繪喜歡的插畫人物,那個專注在筆觸和色彩的過程,就像在幫心靈按摩一樣,讓緊繃的神經慢慢鬆開。
Thumbnail
身為一個典型的社畜,上班時間被會議、進度、KPI 塞得滿滿,下班後只想要找一個能夠安靜喘口氣的小角落。對我來說,畫畫就是那個屬於自己的小樹洞。無論是胡亂塗鴉,還是慢慢描繪喜歡的插畫人物,那個專注在筆觸和色彩的過程,就像在幫心靈按摩一樣,讓緊繃的神經慢慢鬆開。
Thumbnail
題目敘述 Combination Sum II_Leetcode #40 給定一個整數陣列candidates 和 目標值target。 每個陣列元素只能選擇一次,請問有多少種組合方法,可以使得組合數總和 = target? 請把滿足組合數總和 = target的組合方法以陣列的形式返回答案
Thumbnail
題目敘述 Combination Sum II_Leetcode #40 給定一個整數陣列candidates 和 目標值target。 每個陣列元素只能選擇一次,請問有多少種組合方法,可以使得組合數總和 = target? 請把滿足組合數總和 = target的組合方法以陣列的形式返回答案
Thumbnail
題目敘述 Combination Sum IV 給定一個輸入陣列nums,和目標值target,從nums裡面挑數字去湊出總和 = target,數字可以重複挑選。 請問有多少排列數可以湊出target? 註: 排列數的意思就是位置不同代表兩種不同的方法數。
Thumbnail
題目敘述 Combination Sum IV 給定一個輸入陣列nums,和目標值target,從nums裡面挑數字去湊出總和 = target,數字可以重複挑選。 請問有多少排列數可以湊出target? 註: 排列數的意思就是位置不同代表兩種不同的方法數。
Thumbnail
題目敘述 Single Number III 給定一個輸入陣列,已知有兩個烙單的數字,其他剩餘的數字都恰巧出現兩次。 請找出這兩個烙單的數字。 題目額外提出限制,請使用O(n)線性時間、O(1)常數空間複雜度的演算法。 測試範例 Example 1: Input: nums = [1,
Thumbnail
題目敘述 Single Number III 給定一個輸入陣列,已知有兩個烙單的數字,其他剩餘的數字都恰巧出現兩次。 請找出這兩個烙單的數字。 題目額外提出限制,請使用O(n)線性時間、O(1)常數空間複雜度的演算法。 測試範例 Example 1: Input: nums = [1,
Thumbnail
Leetcode 精選75題 題目與題解 熱門考點 目錄 (持續更新中) 建議從左側目錄 或者 按Ctrl+F輸入關鍵字進行搜尋
Thumbnail
Leetcode 精選75題 題目與題解 熱門考點 目錄 (持續更新中) 建議從左側目錄 或者 按Ctrl+F輸入關鍵字進行搜尋
Thumbnail
子集合生成是一道經典的組合類上機考和面試題目。本篇文章介紹多個不同的解決方案,以及相關演算法框架。主要目標是給定n個相異的元素,產生所有的子集合。
Thumbnail
子集合生成是一道經典的組合類上機考和面試題目。本篇文章介紹多個不同的解決方案,以及相關演算法框架。主要目標是給定n個相異的元素,產生所有的子集合。
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
Thumbnail
題目會給定一個陣列nums和一個目標值goal。計算子陣列總和=goal的數目有多少。演算法包含前綴和和字典的技巧,時間複雜度為O(n),空間複雜度為O(n)。
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
題目敘述 題目會給定我們一個整數陣列nums,我們每回合可以挑選總和為K的兩個數字,形成一個K-Sum pair。 請問我們最多可以製造幾個K-Sum pair? 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4], k = 5 Output
Thumbnail
題目敘述 題目會給定我們一個整數陣列nums,我們每回合可以挑選總和為K的兩個數字,形成一個K-Sum pair。 請問我們最多可以製造幾個K-Sum pair? 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4], k = 5 Output
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News