[代码随想录]Day37-动态规划part05
题目:1049. 最后一块石头的重量 II
思路:
和昨天的类似,越靠近和的一半剩下的就越少。
相对于 01背包,本题中,石头的重量是 stones[i],石头的价值也是 stones[i] ,可以 “最多可以装的价值为 dp[j]” == “最多可以背的重量为dp[j]”
代码:
func lastStoneWeightII(stones []int) int {
sum := 0
for _, x := range stones {
sum += x
}
half := sum / 2
dp := make([]int, half+1)
for i:=0; i <len(stones); i++ {
for j := half; j >= stones[i]; j-- {
dp[j] = max(dp[j],dp[j-stones[i]]+stones[i])
}
}
return sum - 2 * dp[half]
}
func max(a,b int) int {
if a > b {
return a
}
return b
}
参考:
题目:494. 目标和
思路:
本题要如何使表达式结果为target,既然为target,那么就一定有 left组合 - right组合 = target。left + right = sum
,而sum是固定的。right = sum - left
公式来了, left - (sum - left) = target
推导出 left = (target + sum)/2
。
target是固定的,sum是固定的,left就可以求出来。
此时问题就是在集合nums中找出和为left的组合。
有哪些来源可以推出dp[j]呢?
只要搞到nums[i],凑成dp[j]就有dp[j - nums[i]] 种方法。
例如:dp[j],j 为5,
- 已经有一个1(nums[i]) 的话,有 dp[4]种方法 凑成 容量为5的背包。
- 已经有一个2(nums[i]) 的话,有 dp[3]种方法 凑成 容量为5的背包。
- 已经有一个3(nums[i]) 的话,有 dp[2]中方法 凑成 容量为5的背包
- 已经有一个4(nums[i]) 的话,有 dp[1]中方法 凑成 容量为5的背包
- 已经有一个5 (nums[i])的话,有 dp[0]中方法 凑成 容量为5的背包
那么凑整dp[5]有多少方法呢,也就是把 所有的 dp[j - nums[i]] 累加起来。
代码:
func findTargetSumWays(nums []int, target int) int {
sum := 0
for _ , x := range nums {
sum += x
}
if abs(target) > sum {
return 0
}
if (sum + target) % 2 != 0 {
return 0
}
mx := (sum + target) / 2 // 只要有这个数就可以
dp := make([]int, mx + 1)
dp[0] = 1
for i:=0;i<len(nums);i++ {
for j:=mx;j>=nums[i];j--{
dp[j] += dp[j-nums[i]]
}
}
return dp[mx]
}
func abs(a int) int {
if a < 0 {
return -a
}
return a
}
参考:
题目:474. 一和零
思路:
dp[i][j] 可以由前一个strs里的字符串推导出来,strs里的字符串有zeroNum个0,oneNum个1。
dp[i][j] 就可以是 dp[i - zeroNum][j - oneNum] + 1。
然后我们在遍历的过程中,取dp[i][j]的最大值。
所以递推公式:dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
此时大家可以回想一下01背包的递推公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
对比一下就会发现,字符串的zeroNum和oneNum相当于物品的重量(weight[i]),字符串本身的个数相当于物品的价值(value[i])。
这就是一个典型的01背包! 只不过物品的重量有了两个维度而已。
代码:
func findMaxForm(strs []string, m int, n int) int {
dp := make([][]int, m+1)
for i, _ := range dp {
dp[i] = make([]int, n+1)
}
for i:=0;i<len(strs);i++ {
zeroNum, oneNum := Calc(strs[i])
for j:=m;j>=zeroNum;j-- {
for k:=n;k>=oneNum;k-- {
dp[j][k] = max(dp[j][k], dp[j-zeroNum][k-oneNum]+1)
}
}
}
return dp[m][n]
}
func max(a,b int)int {
if a > b {
return a
}
return b
}
func Calc(s string)(zero, one int) {
for _, v := range s {
if v == '0' {
zero++
}else {
one++
}
}
return
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!