代码随想录算法训练营第四十二、三天| 01背包、LeetCode416. 分割等和子集、LeetCode1049.最后一块石头的重量II、Leetcode494.目标和、Leetcode474.一和零

416. 分割等和子集

题目描述: 416. 分割等和子集.

解法

二维dp
class Solution(object):
    def canPartition(self, nums):
        sum_nums = sum(nums)
        if sum_nums % 2 == 1:
            return False
        half = sum(nums)//2
        count_nums = len(nums)
        dp = [[0] * (half + 1) for _ in range(count_nums)]
        
        for j in range(half + 1):
            if j >= nums[0]:
                dp[0][j] = nums[0]
        
        for i in range(1,count_nums):
            for j in range(1,half+1):
                if j >= nums[i]:
                    dp[i][j] = max(dp[i-1][j],dp[i-1][j-nums[i]] + nums[i])
                else:
                    dp[i][j] = dp[i-1][j]
        return dp[count_nums-1][half] == half
滚动dp
class Solution(object):
    def canPartition(self, nums):
        sum_nums = sum(nums)
        if sum_nums%2 == 1:
            return False
        half = sum_nums // 2
        count_nums = len(nums)

        dp = [0] * (half + 1)

        for i in range(count_nums):
            for j in range(half, nums[i] - 1, -1):
                dp[j] = max(dp[j],dp[j-nums[i]] + nums[i])
        return dp[half] == half

主要思路就是,用half当作背包的容量,nums作为重量和价值,half作为容量能保证重量不会超过half,也就保证了价值不会超过half,找到容量为half的背包所能拥有的最大价值,如果等于half,那就是由能正好平分整个sum的几个数字,自然就能分割等和子集了。

1049.最后一块石头的重量II

题目描述: 1049.最后一块石头的重量II.

解法

二维dp
class Solution(object):
    def lastStoneWeightII(self, stones):
        stone_nums = len(stones)
        all_weight = sum(stones)
        half = all_weight // 2
        dp = [[0] * (half + 1) for _ in range(stone_nums)]

        for j in range(half+1):
            if j >= stones[0]:
                dp[0][j] = stones[0]
        
        for i in range(1,stone_nums):
            for j in range(1,half + 1):
                if j >= stones[i]:
                    dp[i][j] = max(dp[i-1][j],dp[i-1][j-stones[i]]+stones[i])
                else:
                    dp[i][j] = dp[i-1][j]
        return all_weight- 2 * dp[stone_nums-1][half]

一个满容量为half的,最多能装多少价值的东西,价值和重量代表的内容一样。最后用sum- 2 * dp[half]即可

滚动dp
class Solution(object):
    def lastStoneWeightII(self, stones):
        nums_stones = len(stones)
        all_weight = sum(stones)
        half = all_weight // 2
        dp = [0] * (half+1)

        for i in range(nums_stones):
            for j in range(half,-1,-1):
                if j >= stones[i]:
                    dp[j] = max(dp[j],dp[j-stones[i]]+stones[i])
        return all_weight - 2*dp[half] 

494.目标和

题目描述: 494.目标和.

解法

二维dp(不从0初始化)
class Solution(object):
    def findTargetSumWays(self, nums, target):
        sum_nums = sum(nums)
        length_nums = len(nums)
        if abs(target) > sum_nums:
            return 0
        if (sum_nums + target) % 2 != 0:
            return 0
        add_sum = (sum_nums + target) // 2

        dp = [[0] * (add_sum + 1) for _ in range(length_nums)]
        dp[0][0] = 1
        if nums[0] <= add_sum:
            if nums[0] == 0:
                dp[0][nums[0]] = 2
            else:
                dp[0][nums[0]] = 1

        for i in range(1, length_nums):
            for j in range(add_sum + 1):
                dp[i][j] = dp[i-1][j]
                if j-nums[i]>=0:
                    dp[i][j] += dp[i-1][j-nums[i]]
        return dp[length_nums-1][add_sum]

如果不从0初始化,那就要把所有初始化全都考虑清楚

二维dp(从0初始化)
class Solution(object):
    def findTargetSumWays(self, nums, target):
        sum_nums = sum(nums)
        length = len(nums)
        if abs(target) > sum_nums:
            return 0
        if (target + sum_nums) % 2 != 0:
            return 0
        add_sum = (target + sum_nums) // 2

        dp = [[0] * (add_sum + 1) for _ in range(length+1)]
        dp[0][0] = 1

        for i in range(1,length+1):
            for j in range(add_sum+1):
                dp[i][j] = dp[i-1][j]
                if j>=nums[i-1]:
                    dp[i][j] += dp[i-1][j-nums[i-1]]
        return dp[length][add_sum]
滚动dp(从0初始化)
class Solution(object):
    def findTargetSumWays(self, nums, target):
        sum_nums = sum(nums)
        length = len(nums)
        if abs(target) > sum_nums:
            return 0
        if (target + sum_nums) % 2 != 0:
            return 0
        add_sum = (target + sum_nums) // 2

        dp = [0] * (add_sum+1)
        dp[0] = 1
        for i in range(length):
            for j in range(add_sum,-1,-1):
                if j >= nums[i]:
                    dp[j] += dp[j-nums[i]]
        return dp[add_sum]

1049.最后一块石头的重量II

题目描述: 1049.最后一块石头的重量II.

解法

滚动dp
class Solution(object):
    def findMaxForm(self, strs, m, n):
        dp = [[0] * (n+1) for _ in range(m+1)]
        for s in strs:
            zero_num = 0
            one_num = 0
            for num in s:
                if num == '0':
                    zero_num += 1
                else:
                    one_num += 1
            for i in range(m,zero_num-1,-1):
                for j in range(n,one_num-1,-1):
                    dp[i][j] = max(dp[i][j],dp[i-zero_num][j-one_num]+1)
        return dp[m][n]

这本身还是一维的dp。只不过用两个维度表示一个背包。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值