Leetcode 377:組合總和 Ⅳ(最詳細的解法!!!)
阿新 • • 發佈:2018-12-12
給定一個由正整陣列成且不存在重複數字的陣列,找出和為給定目標正整數的組合的個數。
示例:
nums = [1, 2, 3]
target = 4
所有可能的組合為:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
請注意,順序不同的序列被視作不同的組合。
因此輸出為 7。
進階: 如果給定的陣列中含有負數會怎麼樣? 問題會產生什麼變化? 我們需要在題目中新增什麼限制來允許負數的出現?
解題思路
這是之前問題的變種
注意,實際這裡的問題和39
更貼近,我們可以先嚐試能不能從之前問題中得到啟發。我們直接在原問題上修改
class Solution:
def combinationSum4(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if not nums:
return 0
result = list()
nums.sort()
self._combinationSum4(nums, target, list(), result)
return len(result)
def _combinationSum4(self, nums, target, path, res):
if target == 0:
res.append(path)
return
if target < nums[0]:
return
for i in range(len(nums)):
self._combinationSum4(nums, target-nums[i], path+[nums[i]], res)
但是這種解法的速度實在太慢了,我們每次都要重新便利一次nums
。所以我們可以通過記憶化搜尋的方法對這個問題進行優化。
class Solution:
def combinationSum4(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
mem = [None]*(target+1)
nums.sort()
return self._combinationSum4(nums, target, mem)
def _combinationSum4(self, nums, target, mem):
if target == 0:
return 1
if mem[target] != None:
return mem[target]
mem[target] = 0
for num in nums:
if num > target:
break
mem[target] += self._combinationSum4(nums, target - num, mem)
return mem[target]
實際上這個問題我們可以通過動態規劃的方法解決,對於題目中的例子來說,我們要知道target=4
有多少組解,我們只需要知道target=3,2,1
個有多少組解,然後將它們加起來即可。
class Solution:
def combinationSum4(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
mem = [0]*(target + 1)
mem[0] = 1
for i in range(1, target +1):
for num in nums:
if i >= num:
mem[i] += mem[i - num]
return mem[target]
但是這個問題到此還沒有結束,我們因該思考一下這個進階問題,如果有負數會怎麼樣?如果存在負數的話,我們就需要在問題中新增nums
中個元素使用次數的限制,否則會出現無限種可能,例如nums=[-1,1] target=0
。OK!!!所有問題解決。
如有問題,希望大家指出!!!