經典啓蒙:子數和


遞歸暴力

看到題,二話不說直接遞歸,然後果斷超時。

class Solution:
    def __init__(self):
        self.counts=0
    def helper(self,nums,target,start):
        if start ==len(nums):
            if target==0:
                self.counts+=1
            return
        self.helper(nums,target-nums[start],start+1)
        self.helper(nums,target+nums[start],start+1)
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        self.helper(nums,target,0)
        return self.counts

記事本 dp

target和start顯然是變量,可以作爲狀態記錄當前(target,start)對應的解的個數。

class Solution:
    def __init__(self):
        self.d={}
    def helper(self,nums,target,start):
        if start ==len(nums):
            if target==0:
                return 1
            return 0
        if (target,start) in self.d:
            return self.d[target,start]
        t1=self.helper(nums,target-nums[start],start+1)
        self.d[target-nums[start],start+1]=t1
        t2=self.helper(nums,target+nums[start],start+1)
        self.d[target+nums[start],start+1]=t2
        return t1+t2
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        return self.helper(nums,target,0)

揹包dp

如果我們把 nums 劃分成兩個子集 A 和 B,分別代表分配 + 的數和分配 - 的數,那麼他們和 target 存在如下關係:

sum(A) - sum(B) = target
sum(A) = target + sum(B)
sum(A) + sum(A) = target + sum(B) + sum(A)
2 * sum(A) = target + sum(nums)

綜上,可以推出 sum(A) = (target + sum(nums)) / 2,也就是把原問題轉化成:nums 中存在幾個子集 A,使得 A 中元素的和爲 (target + sum(nums)) / 2

但是元素和可能無法整除2 或者 和小於數組所有元素和 = > 不存在解

class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        sums=sum(nums)
        if sums < target or (sums + target) % 2 == 1:
            return 0
        t=(target+sums)//2
        dp=[[0 for i in range(t+1)]for j in range(len(nums)+1)]
        dp[0][0]=1
        for i in range(1,len(nums)+1):
            for j in range(0,t+1):
                if (j<nums[i-1]):
                    dp[i][j]=dp[i-1][j]
                else:
                    dp[i][j]=dp[i-1][j]+dp[i-1][j-nums[i-1]]
        return dp[-1][t]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章