416. 分割等和子集
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200 示例 1 : 输入: [ 1 , 5 , 11 , 5 ]
输出: true
解释: 数组可以分割成 [ 1 , 5 , 5 ] 和 [ 11 ] .
示例 2 : 输入: [ 1 , 2 , 3 , 5 ]
输出: false
解释: 数组不能分割成两个元素和相等的子集.
提示:1 <= nums. length <= 200
1 <= nums[ i] <= 100
思路
数组nums是否可以分为两个和相等的数组。
if sums % 2 : return False
dp[ j] : 在重量为j背包中可装入的最大价值是多少。
dp[ j] = max ( dp[ j] , dp[ j - nums[ i] ] + nums[ i] ) dp定义:
dp = [ 0 ] * ( sums+ 1 ) dp初始化:
不需要初始化,直接为0 就行。使用滑动数组
for i in range ( len ( nums) ) : for j in range ( sums, nums[ i] - 1 ) : dp[ j] = max ( dp[ j] , dp[ j - nums[ i] + nums[ i] )
half1 = sums // 2
if dp[ half1] == half1: return True
else : return False
sums = sum ( nums( ) )
half1 = sums // 2
dp = [ 0 ] * ( half1+ 1 ) for i in range ( len ( nums) ) : for j in range ( half, nums[ i] - 1 ) : dp[ j] = max ( dp[ j] , dp[ j - nums[ i] + nums[ i] )
half1 = sums // 2
if dp[ - 1 ] == half1: return True
else : return False
code python
class Solution : def canPartition ( self, nums: List[ int ] ) - > bool : _sum = 0 for num in nums: _sum += numif _sum % 2 != 0 : return False target = _sum // 2 dp = [ 0 ] * ( target + 1 ) for num in nums: for j in range ( target, num- 1 , - 1 ) : dp[ j] = max ( dp[ j] , dp[ j- num] + num) return dp[ - 1 ] == target
1049.最后一块石头的重量II
有一堆石头,每块石头的重量都是正整数。每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:如果 x == y,那么两块石头都会被完全粉碎;如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y- x。最后,最多只会剩下一块石头。返回此石头最小的可能重量。如果没有石头剩下,就返回 0 。示例:输入:[ 2 , 7 , 4 , 1 , 8 , 1 ]
输出:1
解释:组合 2 和 4 ,得到 2 ,所以数组转化为 [ 2 , 7 , 1 , 8 , 1 ] ,
组合 7 和 8 ,得到 1 ,所以数组转化为 [ 2 , 1 , 1 , 1 ] ,
组合 2 和 1 ,得到 1 ,所以数组转化为 [ 1 , 1 , 1 ] ,
组合 1 和 1 ,得到 0 ,所以数组转化为 [ 1 ] ,这就是最优值。
提示:1 <= stones. length <= 30
1 <= stones[ i] <= 1000
思路
sums = sum ( nums)
half1 = sums // 2
dp[ j] : 重量为j的背包可装的最大价值dp[ i]
dp[ j] = max ( dp[ j] , dp[ j- nums[ i] ] + nums[ i] ) dp = [ 0 ] * ( half1 + 1 ) for num in nums: for j in range ( half, num - 1 , - 1 ) dp[ j] = max ( dp[ j] , dp[ j- num] + num) return sums - dp[ half1] * 2
code pyton
class Solution:def lastStoneWeightII(self, stones):total_sum = sum(stones)target = total_sum // 2dp = [0] * (target + 1)for stone in stones:for j in range(target, stone - 1, -1):dp[j] = max(dp[j], dp[j - stone] + stone)return total_sum - 2* dp[-1]
494.目标和
给定一个非负整数数组,a1, a2, . . . , an, 和一个目标数,S。现在你有两个符号 + 和 - 。对于数组中的任意一个整数,你都可以从 + 或 - 中选择一个符号添加在前面。
返回可以使最终数组和为目标数 S 的所有添加符号的方法数。
示例:
输入:nums: [ 1 , 1 , 1 , 1 , 1 ] , S: 3
输出:5
解释:
- 1 + 1 + 1 + 1 + 1 = 3
+ 1 - 1 + 1 + 1 + 1 = 3
+ 1 + 1 - 1 + 1 + 1 = 3
+ 1 + 1 + 1 - 1 + 1 = 3
+ 1 + 1 + 1 + 1 - 1 = 3 一共有5 种方法让最终目标和为3 。
提示:
数组非空,且长度不会超过 20 。
初始的数组的和不会超过 1000 。
保证返回的最终结果能被 32 位整数存下。
思路
left和 + right和 = sums
left和 - right和 = target
left和 = ( sums + target) / 2
其中,target, sums确定
dp[ j] = 和为j的方法数
sums = sum ( nums)
left = ( sums + target) / 2 if left % 2 : return 0
if ( abs ( s) > sums) : return 0
dp = [ 0 ] * ( sums + 1 )
dp[ 0 ] = 1
for num in nums: for j in range ( sums, num- 1 , - 1 ) : dp[ j] += dp[ j- num]
return dp[ left]
code
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 ) dp[ 0 ] = 1 for num in nums: for j in range ( target_sum, num - 1 , - 1 ) : dp[ j] += dp[ j - num] return dp[ target_sum]
回溯方法
class Solution : def backtracking ( self, candidates, target, total, startIndex, path, result) : if total == target: result. append( path[ : ] ) for i in range ( startIndex, len ( candidates) ) : if total + candidates[ i] > target: break total += candidates[ i] path. append( candidates[ i] ) self. backtracking( candidates, target, total, i + 1 , path, result) total -= candidates[ i] path. pop( ) def findTargetSumWays ( self, nums: List[ int ] , target: int ) - > int : total = sum ( nums) if target > total: return 0 if ( target + total) % 2 != 0 : return 0 bagSize = ( target + total) // 2 result = [ ] nums. sort( ) self. backtracking( nums, bagSize, 0 , 0 , [ ] , result) return len ( result)
474.一和零
给你一个二进制字符串数组 strs 和两个整数 m 和 n 。请你找出并返回 strs 的最大子集的大小,该子集中 最多 有 m 个 0 和 n 个 1 。如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。示例 1 :
输入:strs = [ "10" , "0001" , "111001" , "1" , "0" ] , m = 5 , n = 3
输出:4 解释:最多有 5 个 0 和 3 个 1 的最大子集是 { "10" , "0001" , "1" , "0" } ,因此答案是 4 。 其他满足题意但较小的子集包括 { "0001" , "1" } 和 { "10" , "1" , "0" } 。{ "111001" } 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。示例 2 :
输入:strs = [ "10" , "0" , "1" ] , m = 1 , n = 1
输出:2
解释:最大的子集是 { "0" , "1" } ,所以答案是 2 。
提示:1 <= strs. length <= 600
1 <= strs[ i] . length <= 100
strs[ i] 仅由 '0' 和 '1' 组成
1 <= m, n <= 100
思路
dp[ i] [ j] 0 的最大个数<= i, 1 的最大个数<= j的字符串最大个数为dp[ i] [ j] dp[ i] [ j] = max ( dp[ i] [ j] , dp[ i- cur0] [ j- cur1] + 1 )
dp[ j] = max ( dp[ j] , dp[ j- weigh[ i] ] + value[ i] ) dp[ i] [ j] = [ [ 0 ] * ( n + 1 ) ] * ( m + 1 )
dp[ 0 ] [ 0 ] = 1 strs = [ "10" , "0001" , "111001" , "1" , "0" ]
v = "10"
cur0, cur1 = 1 , 1
dp[ 5 ] [ 3 ]
for i in range ( 5 , - 1 ) :
forj in range ( 3 , - 1 , - 1 ) : if i >= 1 and j >= 1 : dp[ i] [ j] = 1 v = "0001"
cur0, cur1 = 3 , 1
for i in range ( 5 , - 1 ) :
forj in range ( 3 , - 1 , - 1 ) : if i >= 3 and j >= 1 : dp[ i] [ j] = max ( dp[ i] [ j] , dp[ i- 3 ] [ j- 1 ] + 1 ) v = "111001"
cur0, cur1 = 2 , 4
for i in range ( 5 , - 1 ) :
forj in range ( 3 , - 1 , - 1 ) : if i >= 2 and j >= 4 : dp[ i] [ j] = max ( dp[ i] [ j] , dp[ i- 2 ] [ j- 4 ] + 1 ) v = "1"
cur0, cur1 = 0 , 1
for i in range ( 5 , - 1 ) :
forj in range ( 3 , - 1 , - 1 ) : if i >= 0 and j >= 1 : dp[ i] [ j] = max ( dp[ i] [ j] , dp[ i- 0 ] [ j- 1 ] + 1 ) v = "0"
cur0, cur1 = 1 , 0
for i in range ( 5 , - 1 ) :
forj in range ( 3 , - 1 , - 1 ) : if i >= 1 and j >= 0 : dp[ i] [ j] = max ( dp[ i] [ j] , dp[ i- 1 ] [ j- 0 ] + 1 ) def counts1 ( str1) : cur0, cur1 = 0 , 0 for v in str1: if v == '1' : cur1 += 1 else : cur0 += 1 return cur0, cur1for v in strs: cur0, cur1 = counts1( v) for i in range ( n, - 1 , - 1 ) : for j in range ( m, - 1 , - 1 ) : if i >= cur0 and j >= cur1: dp[ i] [ j] = max ( dp[ i] [ j] , dp[ i- cur0] [ j- cur1] + 1 )