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。只不过用两个维度表示一个背包。