前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >LeetCode:一和零_474

LeetCode:一和零_474

作者头像
Yuyy
发布2022-06-28 20:40:58
发布2022-06-28 20:40:58
12000
代码可运行
举报
运行总次数:0
代码可运行

思路

多维的动态规划,属于背包类问题,只是穷举多了个背包。

strs里的每个元素就是物品,m为装1的背包数量,n为装0的背包数量,开始DP套路:

代码语言:javascript
代码运行次数:0
复制
定义状态:dp[i][m][n]表示0-i个物品,m个装1的背包,n个装0的背包可以装下多少个物品
状态转移方程:dp[i][m][n]=max(dp[i-1][m][n],dp[i-1][m-i1][n-i0]+1)
初始值:dp[0][m][n]=0

优化

由于dp[i][m][n]的取值都来源于dp[i-1][m][n],那么可以直接用二维数组,只是每次放物品时,都在同一个二维数组上操作,也就是基于上一个物品的二维数组计算。这就是滚动数组的由来,需要满足的条件是:上一层可以重复利用,直接拷贝到当前层。

正序遍历背包数量时,三维数组用到了dp[i-1][m-i1][n-i0],现在是dp[m-i1][n-i0],因为是正序,所以这个值是在dp[m][n]计算前就计算过了,也就是被覆盖了,不再等于dp[i-1][m-i1][n-i0]。而后序遍历可以正常计算,计算dp[m][n]时,dp[m-i1][n-i0]还没使用过,就是之前的值。

题目

代码

代码语言:javascript
代码运行次数:0
复制
func findMaxFormOld(strs []string, m int, n int) int {
    dp := iniDpArr(strs, m, n)
    for i, str := range strs {
        zeroCount, oneCount := countOfZeroAndOne(str)
        // 当前物品固定,穷举背包数量
        for j := 0; j <= m; j++ {
            for k := 0; k <= n; k++ {
                // 装不下该物品 = 不装
                if j < zeroCount || k < oneCount {
                    dp[i+1][j][k] = dp[i][j][k]
                } else {
                    dp[i+1][j][k] = max(dp[i][j][k], dp[i][j-zeroCount][k-oneCount]+1)
                }
            }
        }
    }
    return dp[len(strs)][m][n]
}

// 优化后
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 _, s := range strs {
        zeros := strings.Count(s, "0")
        ones := len(s) - zeros
        for j := m; j >= zeros; j-- {
            for k := n; k >= ones; k-- {
                dp[j][k] = max(dp[j][k], dp[j-zeros][k-ones]+1)
            }
        }
    }
    return dp[m][n]
}

func countOfZeroAndOne(str string) (int, int) {
    var zeroCount, oneCount int
    for _, char := range str {
        if '0' == char {
            zeroCount++
        } else if '1' == char {
            oneCount++
        }
    }
    return zeroCount, oneCount
}

func iniDpArr(strs []string, m int, n int) [][][]int {
    var dp = make([][][]int, len(strs)+1)
    for i := range dp {
        dp[i] = make([][]int, m+1)
        for j := range dp[i] {
            dp[i][j] = make([]int, n+1)
        }
    }
    return dp
}

func max(i int, i2 int) int {
    if i > i2 {
        return i
    }
    return i2
}

动态规划:关于01背包问题,你该了解这些!(滚动数组)

Post Views: 24

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-5-28 1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 思路
    • 优化
  • 题目
  • 代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档