tasks for today:
1. 1049.最后一块石头的重量II
2. 494.目标和
3. 474.一和零
--------------------------------------------------------------------------
1. 1049.最后一块石头的重量II
本题其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小,这样就化解成01背包问题了
This is similar to the practice 416, the only difference is the return value
def lastStoneWeightII(self, stones: List[int]) -> int:
if len(stones) == 1:
return stones[0]
target = sum(stones) // 2
dp = [0] * (target + 1)
for i in range(0, len(stones)):
# method 1
for j in range(target, 0, -1):
if j >= stones[i]:
dp[j] = max(dp[j], dp[j-stones[i]] + stones[i])
# method 2
# for j in range(target, stones[i] - 1, -1):
# dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])
return (sum(stones) - dp[-1]) - dp[-1]
2. 494.目标和
In this practice, the first thought leading it to a 01 backpack problem would be the separtion of two group, this also stress the importance of the practice 416, which serve as the basic idea for a lot of practices.
SO the essence of this practice is to find the proper bagsize first, which is derived by following two equations: left + right = sum; left - right = target -> then the left = (sum+target)/2 would be the bagsize.
1st pitfall: special condition for return 0
2nd pitfall: the target for judging target and sum should be processed by abs()
3rd pitfall: the initialization of dp, the fist entry should be 1, while the left are all 0, this is subject to the recursive equation, which is not max() anymore, instead, it is cululating.
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
if (sum(nums) + target) % 2 == 1: return 0
if abs(target) > sum(nums): return 0
bagsize = (sum(nums) + target) // 2
dp = [0] * (bagsize + 1)
dp[0] = 1
for i in range(len(nums)):
# method 1
for j in range(bagsize, 0, -1):
if j >= nums[i]:
dp[j] += dp[j-nums[i]]
# method 2
for j in range(bagsize, nums[i]-1, -1):
dp[j] += dp[j-nums[i]]
return dp[-1]
3. 474.一和零
In this practice, there are two constraint dimentions for the backpack, which is the amount of "0" and "1", so the correspodning weight list and value list should also be two dimentions. in this practice, the dp store the max number, so there is no value list.
pay attention to the initial construction of dp list, i.e., the sequence of m and n
class Solution:
def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
dp = [[0] * (n+1) for _ in range(m+1)]
for i in range(len(strs)):
zero_num = strs[i].count('0')
one_num = len(strs[i]) - zero_num
for j in range(m, zero_num-1, -1):
for k in range(n, one_num-1, -1):
dp[j][k] = max(dp[j][k], dp[j-zero_num][k-one_num] + 1)
return dp[-1][-1]