代码随想录算法训练营|day43

1049.最后一块石头的重量II

每次选出的两块石头重量越接近,最后剩余的重量越轻
将石头分成两堆,寻找重量轻的那一堆石头的最大值maxWeight,则另一堆石头重量为sum-maxWeight,最终结果为sum-2*maxWeight,因此定义背包容量target = sum(nums)/2
dp[i]表示背包容量为i时,能装到的最大石头重量。

func lastStoneWeightII(stones []int) int {
	sum := 0
	for _, stone := range stones {
		sum += stone
	}
	target := sum / 2
	dp := make([]int, target+1)
	for _, stone := range stones {
		for i := target; i >= stone; i-- {
			dp[i] = max(dp[i], dp[i-stone]+stone)
		}
	}
	return sum - 2*dp[target]
}

494.目标和

假设组成的等式中被减数为left,减数为right,和为sum,题意为寻找满足left-right=target的个数,改写成left-(sum-left)=target,即为寻找数组中满足left=(sum+target)/2的个数。
dp[i]表示背包容量为i时,有dp[i]种方法能装满背包。若abs(target)<abs(sum)被减数为小数,无解

func findTargetSumWays(nums []int, target int) int {
	sum := 0
	for _, num := range nums {
		sum += num
	}
	if abs(sum) < abs(target) || (sum+target)%2 == 1 {
		return 0
	}
	left := (sum + target) / 2
	dp := make([]int, left+1)
	dp[0] = 1
	for _, num := range nums {
		for i := left; i >= num; i-- {
			dp[i] += dp[i-num]
		}
	}
	return dp[left]
}

func abs(x int) int {
	return int(math.Abs(float64(x)))
}

474.一和零

dp[i][j]表示背包容量为i,j时,能用str装满背包的个数,即strs子集的个数

func findMaxForm(strs []string, m int, n int) int {
	dp := make([][]int, m + 1)
	for i := 0; i < m + 1; i++ {
		dp[i] = make([]int, n + 1)
	}
	for _, str := range strs {
		zeros, ones := countZerosAndOnes(str)[0], countZerosAndOnes(str)[1]
		for i := m; i >= zeros; i-- {
			for j := n; j >= ones; j-- {
				dp[i][j] = max(dp[i][j], dp[i-zeros][j-ones]+1)
			}
		}
	}
	return dp[m][n]
}

func countZerosAndOnes(str string) []int {
	count := make([]int, 2)
	for _, c := range str {
		count[c-'0']++
	}
	return count
}

代码随想录文章详解

1049.最后一块石头的重量II
494.目标和
474.一和零

总结

求装满背包有几种方法的情况下,递推公式一般为:dp[j] += dp[j - nums[i]]
没得选和可选可不选

  • 34
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值