LeetCode Day 43 Dynamic Programming (5/17)
Published:
Its 5th Day of DP practice.
Question 1
You are given an array of integers
stoneswherestones[i]is the weight of theithstone.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
xandywithx <= y. The result of this smash is:
- If
x == y, both stones are destroyed, and- If
x != y, the stone of weightxis destroyed, and the stone of weightyhas 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.
This problem is really about trying to get the stones to split into two piles of the same weight, with the smallest number of stones left after collision, which resolves into the 01 Knapsack problem.
The weight of the items in this problem is stones[i], and the value of the items is also stones[i]. This corresponds to the weight[i] and value[i] of the items in 01pack. The rest of the process is similar.
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]
Question 2
You are given an integer array
numsand 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'+'before2and a'-'before1and concatenate them to build the expression"+2-1".Return the number of different expressions that you can build, which evaluates to
target.
Suppose the sum of addition is x, then the corresponding sum of subtraction is sum - x.
So we require x - (sum - x) = target
x = (target + sum) / 2
At this point the Knapsack problem transforms into, how many ways to fill a knapsack of capacity x.
Here, x, is bagSize, which is the capacity of the backpack we ask for later.
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]
Question 3
You are given an array of binary strings
strsand two integersmandn.Return the size of the largest subset of
strssuch that there are at mostm0’s andn1’s in the subset.A set
xis a subset of a setyif all elements ofxare also elements ofy.
This question looks complicated at first glance, like a brain teaser.
The elements in the strs array in this question are the items, one for each item! And m and n are equivalent to a knapsack, in two dimensions.
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]
