数据结构算法刷题:背包问题

数据结构算法刷题:背包问题_第1张图片

数据结构算法刷题:背包问题_第2张图片

数据结构算法刷题:背包问题_第3张图片

数据结构算法刷题:背包问题_第4张图片

整数和是p,负数和是s-p,那么target = p - (s-p),求出p = (s+t)//2

class Solution:

    def findTargetSumWays(self, nums: List[int], target: int) -> int:

        target += sum(nums)

        if target < 0 or target % 2: #target 一定是偶数而且是大于0 

            return 0

        target = target // 2

        n = len(nums)

        @cache   #cache是将传参和返回记录下来,避免了重复计算

        def dfs(i,c):

            if i < 0:

                return 1 if c == 0 else 0 #如果c小于0,那就没有找到,返回0,c==0返回1

            if nums[i] > c: #当前值大于c,不能选

                return dfs(i-1,c)

            return dfs(i-1,c)+dfs(i-1,c-nums[i]) #返回选或者不选的和

        return dfs(n-1,target)

改成递推的形式

class Solution:

    def findTargetSumWays(self, nums: List[int], target: int) -> int:

        target += sum(nums)

        if target < 0 or target % 2:

            return 0

        target = target // 2

        n = len(nums)

        dp = [[0]*(target+1) for i in range(n+1)]

        dp[0][0] = 1 #初始化

        for i,x in enumerate(nums):

            for c in range(target+1):

                if c < x: #不选

                    dp[i+1][c] = dp[i][c]

                else: #选+不选

                    dp[i+1][c] = dp[i][c] + dp[i][c-x]

        return dp[-1][-1]

数据结构算法刷题:背包问题_第5张图片

数据结构算法刷题:背包问题_第6张图片

class Solution:

    def coinChange(self, coins: List[int], amount: int) -> int:

        #完全背包,对于完全背包,每次选择之后,还可以继续选。

        n = len(coins)

        @cache

        def dfs(i,c):

            if i < 0:

                return 0 if c == 0 else inf #如果当前不满足条件就返回无穷

            if c < coins[i]: #不选

                return dfs(i-1,c)

            return min(dfs(i-1,c),dfs(i,c-coins[i])+1) #选的时候不能是i-1,因为选了可以再选

        a = dfs(n-1,amount)

        return a if a < inf else -1

改成递推的形式

class Solution:

    def coinChange(self, coins: List[int], amount: int) -> int:

        n = len(coins)

        dp = [[inf]*(amount+1) for i in range(n+1)]

        dp[0][0] = 0

        for i,x in enumerate(coins):

            for c in range(amount+1):

                if x > c:

                    dp[i+1][c] = dp[i][c] #不选,往下走

                else:

                    dp[i+1][c] =min(dp[i][c],dp[i+1][c-x]+1) #选了还可以继续选i+1

        ans = dp[-1][-1]

        return ans if ans < inf else -1    

数据结构算法刷题:背包问题_第7张图片

在例题494中,如果是至多是target。那就在边界条件时不需要判断,初始化dp全部为1.

class Solution:

    def findTargetSumWays(self, nums: List[int], target: int) -> int:

        target += sum(nums)

        if target < 0 or target % 2:

            return 0

        target = target // 2

        n = len(nums)

        dp = [[1]*(target+1) for i in range(n+1)]

        for i,x in enumerate(nums):

            for c in range(target+1):

                if c < x: #不选

                    dp[i+1][c] = dp[i][c]

                else: #选+不选

                    dp[i+1][c] = dp[i][c] + dp[i][c-x]

        return dp[-1][-1]

class Solution:

    def findTargetSumWays(self, nums: List[int], target: int) -> int:

        target += sum(nums)

        if target < 0 or target % 2: #target 一定是偶数而且是大于0 

            return 0

        target = target // 2

        n = len(nums)

        @cache   #cache是将传参和返回记录下来,避免了重复计算

        def dfs(i,c):

            if i < 0:

                return 1 

            if nums[i] > c: #当前值大于c,不能选

                return dfs(i-1,c)

            return dfs(i-1,c)+dfs(i-1,c-nums[i]) #返回选或者不选的和

        return dfs(n-1,target)

如果是至少为target,那就是比target大也可以。

class Solution:

    def findTargetSumWays(self, nums: List[int], target: int) -> int:

        target += sum(nums)

        if target < 0 or target % 2: #target 一定是偶数而且是大于0 

            return 0

        target = target // 2

        n = len(nums)

        @cache   #cache是将传参和返回记录下来,避免了重复计算

        def dfs(i,c):

            if i < 0:

                return 1 if c <= 0 else 0

            return dfs(i-1,c)+dfs(i-1,c-nums[i]) #不会判断nums[i]>c的情况

        return dfs(n-1,target)

你可能感兴趣的:(数据结构)