def findTargetSumWays(self, nums, S):
"""
HuaHuaJiang's Method
算法:動規
元素和是nums_sum,整個數組的元素取值範圍就是[-nums_sum,+nums_sum],所以總共可能有的狀態值就是2*nums_sum+1
因爲列表下標都是正的,所以設定一個offset,
如[1,1,1,1,1],取值範圍是[-5,-4,-3,-2,-1,0,1,2,3,4,5],那麼0那個位置的下標其實是5,所以offset=nums_sum
dp[i][j]代表前i個元素構成j有幾種方式
dp第一維的大小是n+1,這樣就可以把dp[0]用上,代表一個元素都不用的情況
然後底下就是for循環了,如果dp[i][j] != 0的話,那麼:
如果加上nums[i],那麼下一行的dp[i+1][j+nums[i]] += dp[i][j],就是多了從dp[i][j]來的次數
如果減去nums[i],那麼下一行的dp[i+1][j-nums[i]] += dp[i][j],就是多了從dp[i][j]來的次數
這樣便可以從上向下依次推出dp[i][j]的值
最後返回的是dp[n][S+offset],要補上offset,因爲數組下標實際上不是目標值,加上offset後纔是
然後可以看到dp[i]之和dp[i-1]有關係,所以第一維可以去掉,使用滾動數組,將二維dp數組化爲一維dp數組
"""
nums_sum = sum(nums)
offset = nums_sum
if nums_sum < S:
return 0
n = len(nums)
dp = [[0] * (2 * nums_sum + 1) for _ in range(n + 1)]
dp[0][offset] = 1
for i in range(n):
for j in range(2 * nums_sum + 1):
if dp[i][j] != 0:
dp[i + 1][j + nums[i]] += dp[i][j]
dp[i + 1][j - nums[i]] += dp[i][j]
return dp[n][S + offset]
def findTargetSumWays1(self, nums, S):
"""
Brute Force Method
Python TLE Java Accepted
就遞歸,對每個元素進行加或者是減,看看最後到path末端的時候,和是S的話,ans += 1
"""
self.ans = 0
def dfs(index, path_sum):
if index == len(nums):
if path_sum == S:
self.ans += 1
return
dfs(index + 1, path_sum + nums[index])
dfs(index + 1, path_sum + -nums[index])
dfs(0, 0)
return self.ans