JS 动态规划 LeetCode 一和零

一和零

问题

在计算机界中,我们总是追求用有限的资源获取最大的收益。

现在,假设你分别支配着 m 个 0 和 n 个 1。另外,还有一个仅包含 0 和 1 字符串的数组。

你的任务是使用给定的 m 个 0 和 n 个 1 ,找到能拼出存在于数组中的字符串的最大数量。每个 0 和 1 至多被使用一次。

注意:

  1. 给定 0 和 1 的数量都不会超过 100。
  2. 给定字符串数组的长度不会超过 600。

示例 1:

输入: Array = {"10", "0001", "111001", "1", "0"}, m = 5, n = 3
输出: 4

解释: 总共 4 个字符串可以通过 5 个 0 和 3 个 1 拼出,即 "10","0001","1","0" 。

示例 2:

输入: Array = {"10", "0", "1"}, m = 1, n = 1
输出: 2

解释: 你可以拼出 "10",但之后就没有剩余数字了。更好的选择是拼出 "0" 和 "1" 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ones-and-zeroes
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

1. 确定状态

设 f【a】【m】【n】,a表示字符串数组,m表示使用0的个数,n表示使用1的个数。
总体表示在a字符串数组的情况下,使用m个0和n个1可以拼出字符串的最大数量。
M表示新增的字符串需要0的个数。
N表示新增的字符串需要1的个数。

2. 转移方程

f【a】【m】【n】=

  • 拼出新增的字符串,f【a-1】【m-M】【n-N】 + 1
  • 不拼出, f【a-1】【m】【n】

f【a】【m】【n】 = Max(f【a-1】【m-M】【n-N】 + 1, f【a-1】【m】【n】)

3. 初始条件和边界情况

f【0】【m】【n】 = 0
m >= M, n >= N.

由于每个字符串只能使用一次(即有限背包),因此在更新f【m】【n】时, m和n都需要从大到小进行枚举

4. 计算顺序

从小到大

代码

因为不需要存储目前字符串组所以,采用二维数组表示整个状态

/**
 * @param {string[]} strs
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
var findMaxForm = function (strs, m, n) {
  var f = new Array(m + 1);
  for (let i = 0; i < f.length; ++i) {
    f[i] = new Array(n + 1);
    f[i].fill(0);
  }
  console.dir(f);
  for (let s of strs) {
    // 计算strs中m,n的值
    var M = 0;
    var N = 0;
    for (let char of s) {
      if (char == 0) M++;
      else N++;
    }
    for (var i = m; i >= M; i--) {
      for (var j = n; j >= N; j--) {
        f[i][j] = Math.max(f[i - M][j - N] + 1, f[i][j]);
      }
    }
  }
  return f[m][n];
};

原文地址:https://www.cnblogs.com/xiaoxu-xmy/p/13681177.html

原文地址:https://www.cnblogs.com/xiaoxu-xmy/p/13681177.html