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

本文详细解析了三个编程题目,分别是使用动态规划解决的背包问题:1049.最后一块石头的重量II、494.目标和和474.一和零。重点介绍了如何通过递推公式计算背包容量和满足条件的方案数。
摘要由CSDN通过智能技术生成

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]]
没得选和可选可不选

代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值