1. 程式人生 > >Leetcode 377:組合總和 Ⅳ(最詳細的解法!!!)

Leetcode 377:組合總和 Ⅳ(最詳細的解法!!!)

給定一個由正整陣列成且不存在重複數字的陣列,找出和為給定目標正整數的組合的個數。

示例:

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!!!所有問題解決。

如有問題,希望大家指出!!!