动态规划第五天,加油!
You are given an array of integers
stones
wherestones[i]
is the weight of theith
stone.We are playing a game with the stones. On each turn, we choose any two stones and smash them together. Suppose the stones have weights
x
andy
withx <= y
. The result of this smash is:
- If
x == y
, both stones are destroyed, and- If
x != y
, the stone of weightx
is destroyed, and the stone of weighty
has new weighty - x
.At the end of the game, there is at most one stone left.
Return the smallest possible weight of the left stone. If there are no stones left, return
0
.
本题其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小,这样就化解成01背包问题了。
本题物品的重量为stones[i],物品的价值也为stones[i]。对应着01背包里的物品重量weight[i]和 物品价值value[i]。剩下的过程类似。
- class Solution:
- def lastStoneWeightII(self, stones: List[int]) -> int:
- dp = [0] * 15001
- total_sum = sum(stones)
- target = total_sum // 2
-
- for stone in stones:
- for j in range(target, stone - 1, -1):
- dp[j] = max(dp[j], dp[j - stone] + stone)
-
- return total_sum - dp[target] - dp[target]
You are given an integer array
nums
and an integertarget
.You want to build an expression out of nums by adding one of the symbols
'+'
and'-'
before each integer in nums and then concatenate all the integers.
- For example, if
nums = [2, 1]
, you can add a'+'
before2
and a'-'
before1
and concatenate them to build the expression"+2-1"
.Return the number of different expressions that you can build, which evaluates to
target
.
假设加法的总和为x,那么减法对应的总和就是sum - x。
所以我们要求的是 x - (sum - x) = target
x = (target + sum) / 2
此时问题就转化为,装满容量为x的背包,有几种方法。
这里的x,就是bagSize,也就是我们后面要求的背包容量。
- class Solution:
- def findTargetSumWays(self, nums: List[int], target: int) -> int:
- total_sum = sum(nums)
- if abs(target) > total_sum:
- return 0
- if (target + total_sum) % 2 == 1:
- return 0
- target_sum = (target + total_sum) // 2
-
- dp = [[0] * (target_sum + 1) for _ in range(len(nums) + 1)]
-
- dp[0][0] = 1
-
- for i in range(1, len(nums) + 1):
- for j in range(target_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[len(nums)][target_sum]
You are given an array of binary strings
strs
and two integersm
andn
.Return the size of the largest subset of
strs
such that there are at mostm
0
's andn
1
's in the subset.A set
x
is a subset of a sety
if all elements ofx
are also elements ofy
.
这道题乍一看比较复杂,就像一道脑筋急转弯。
本题中strs 数组里的元素就是物品,每个物品都是一个!而m 和 n相当于是一个背包,两个维度的背包。
- class Solution:
- def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
- dp = [[0] * (n + 1) for _ in range(m + 1)]
- for s in strs:
- zeroNum = s.count('0')
- oneNum = len(s) - zeroNum
- for i in range(m, zeroNum - 1, -1):
- for j in range(n, oneNum - 1, -1):
- dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1)
- return dp[m][n]