首页 > 其他分享 >LeetCode题练习与总结:一和零--474

LeetCode题练习与总结:一和零--474

时间:2024-12-17 22:28:57浏览次数:7  
标签:遍历 数组 -- strs length 474 字符串 LeetCode dp

一、题目描述

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

示例 1:

输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
输出:4
解释:最多有 5 个 0 和 3 个 1 的最大子集是 {"10","0001","1","0"} ,因此答案是 4 。
其他满足题意但较小的子集包括 {"0001","1"} 和 {"10","1","0"} 。{"111001"} 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。

示例 2:

输入:strs = ["10", "0", "1"], m = 1, n = 1
输出:2
解释:最大的子集是 {"0", "1"} ,所以答案是 2 。

提示:

  • 1 <= strs.length <= 600
  • 1 <= strs[i].length <= 100
  • strs[i] 仅由 '0' 和 '1' 组成
  • 1 <= m, n <= 100

二、解题思路

这个问题是一个典型的背包问题,更具体地说,是一个二维背包问题。在这个问题中,每个字符串可以被视为一个物品,而每个物品都有两个维度的重量:包含的’0’的数量和包含的’1’的数量。我们的目标是在不超过给定的m个’0’和n个’1’的限制下,尽可能多地选择字符串。

解题思路如下:

  1. 遍历每个字符串,计算每个字符串中’0’和’1’的数量。
  2. 使用动态规划的方法来解决问题。定义一个三维数组dp[i][j][k],表示在前i个字符串中,使用最多j个’0’和k个’1’时可以组成的最大子集的大小。
  3. 对于每个字符串,我们需要决定是否将其包含在子集中。如果包含,我们需要更新dp数组以反映这一选择。
  4. 最后,dp[strs.length][m][n]将包含我们需要的答案。

三、具体代码

class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        // dp[i][j][k] 表示前i个字符串中,最多使用j个0和k个1时的最大子集大小
        int[][][] dp = new int[strs.length + 1][m + 1][n + 1];
        
        // 遍历每个字符串
        for (int i = 1; i <= strs.length; i++) {
            // 计算当前字符串中0和1的数量
            int zeros = 0, ones = 0;
            for (char c : strs[i - 1].toCharArray()) {
                if (c == '0') zeros++;
                else ones++;
            }
            
            // 遍历所有的0和1的容量
            for (int j = 0; j <= m; j++) {
                for (int k = 0; k <= n; k++) {
                    // 如果当前容量可以容纳当前字符串
                    if (j >= zeros && k >= ones) {
                        // 选择当前字符串和不选择当前字符串的最大值
                        dp[i][j][k] = Math.max(dp[i - 1][j][k], dp[i - 1][j - zeros][k - ones] + 1);
                    } else {
                        // 如果不能选择当前字符串,继承上一个状态
                        dp[i][j][k] = dp[i - 1][j][k];
                    }
                }
            }
        }
        
        // 返回最大子集的大小
        return dp[strs.length][m][n];
    }
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 遍历字符串数组:代码中有一个三层嵌套循环,分别对应字符串数组strs的遍历、m的遍历和n的遍历。

    • 字符串数组strs的长度为strs.length,所以外层循环的次数为strs.length
    • 第二层循环变量j从0遍历到m,所以循环次数为m + 1
    • 第三层循环变量k从0遍历到n,所以循环次数为n + 1
  • 计算字符串中0和1的数量:对于每个字符串,需要遍历其所有字符来计算0和1的数量。最坏情况下,每个字符串的长度为100,所以对于每个字符串,这个步骤的时间复杂度为O(100)。

综合以上两点,代码的时间复杂度为: O(strs.length * m * n) * O(字符串最大长度) = O(strs.length * m * n * 100)

2. 空间复杂度
  • 动态规划数组dp:代码中定义了一个三维数组dp,其维度分别为strs.length + 1m + 1n + 1

    • 因此,dp数组总共包含(strs.length + 1) * (m + 1) * (n + 1)个元素。
  • 临时变量:代码中使用了几个临时变量来存储每个字符串中0和1的数量,这些变量的空间复杂度为O(1)。

综合以上两点,代码的空间复杂度为: O(strs.length * m * n)

五、总结知识点

  1. 动态规划(Dynamic Programming):动态规划是一种用于解决优化问题的算法技术,它通过将问题分解为更小的子问题并存储这些子问题的解(即状态)来避免重复计算。

  2. 三维数组:代码中使用了一个三维数组dp来存储子问题的解,其中dp[i][j][k]表示在前i个字符串中,最多使用j个0和k个1时的最大子集大小。

  3. 嵌套循环:代码中使用了三层嵌套循环来遍历字符串数组以及可能的0和1的容量。

  4. 字符串处理:通过toCharArray()方法将字符串转换为字符数组,然后遍历这个数组来计算字符串中0和1的数量。

  5. 条件判断:使用if语句来判断当前容量是否足够容纳当前字符串中的0和1。

  6. 状态转移方程:代码中的dp[i][j][k] = Math.max(dp[i - 1][j][k], dp[i - 1][j - zeros][k - ones] + 1);是动态规划中的状态转移方程,它描述了如何从前一个状态推导出当前状态。

  7. 递推关系:递推关系是动态规划的核心,它定义了如何根据子问题的解来构建更大问题的解。

  8. 数学运算:使用Math.max()函数来比较并选择最大值。

  9. 问题建模:将问题建模为背包问题,其中每个字符串是一个物品,0和1的数量分别是物品的两个维度重量。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

标签:遍历,数组,--,strs,length,474,字符串,LeetCode,dp
From: https://blog.csdn.net/weixin_62860386/article/details/144510548

相关文章

  • 【网络安全】Web安全基础- 第一节:web前置基础知识
    目录前言一、中间件1.1消息中间件1.2数据库中间件1.3web服务器中间件1.4应用服务器中间件1.5远程过程调用中间件二、源码**组成部分:**1、**前端(客户端)代码:**2、**后端(服务器端)代码**:3、资源文件:4、API接口:5、框架和库:6、配置文件:三、数据库四、CDN五、WAF六、DNS解析......
  • 在UE5 Cesium中点击地图生成Spline线
    本文中介绍在UE5Cesium中点击地图生成Spline线步骤包含了:1、鼠标点击时获得屏幕坐标2、将屏幕坐标转成世界坐标3、射线检测找到屏幕坐标在Cesium中的坐标4、生成Spline步骤1、2、3:https://blog.csdn.net/m0_48562356/article/details/144358371步骤4:新建一个Actor,......
  • C语言关于return在循环语句中的使用(求一个数是否为素数的过程中的思考)
    intjk(inta)//定义一个jk函数判断a是否是素数,是返回1,不是则返回0.{ inti;if(a<2){return0;} elseif(a==2) { return1; } else { for(i=2;i<=a-1;i++) { if(a%i==0) { return0; } } return1; } }intmain(......
  • 怎么提高自己的情商和口才?真正受欢迎的人,用这4个技巧提高
    高情商让你能够理解自己和他人的情绪,而良好的口才让你能清晰、自信地表达自己。如何提升情商和口才呢?本文提供实用的方法,让你逐步成长为沟通高手。一、提高情商的方法1.学会识别和管理自己的情绪提高情商的第一步是学会识别自己的情绪,并找到管理情绪的有效方式。情绪管理......
  • 常常被忽略,但是高情商表现的十大特征
    情商,这一概念我们并不陌生,它关乎着我们的情绪、情感,决定着我们处理人际关系的能力。有些人可能认为情商只是一种表面的技巧,但实际上,它却深深影响着我们的生活。情商高的人往往能够更好地处理生活中的各种困难,他们更懂得如何感知他人的情绪,理解他人的需求,从而建立起更为亲密、长......
  • 职场人如何提升职业技能?
    职场人如何提升职业技能?在职场中,每个人都像是一名航行在广阔大海上的水手,面对着不断变化的风浪和挑战。要想在这片职场海洋中稳步前行,甚至脱颖而出,提升职业技能是必不可少的。那么,职场人究竟该如何有效地提升自己的职业技能呢?以下是一些实用而具体的建议。一、持续学习与自我......
  • Hongcow Builds A Nation 题解
    HongcowBuildsANation题解洛谷。Codeforces。题目描述给定一张\(n\)个点,\(m\)条边的无向图,有\(k\)个点是特殊点。每个连通块中都得保证无重边、无自环,且最多只有一个特殊点。求最多还能加多少条边,满足以上条件。思路简述首先考虑以下有\(n\)个点的完全图共有多......
  • 搭建企业NextCloud并集成ONLYOFFICE
    部署安装1.1离线安装​ 使用能够安全拉取nextcloud镜像的服务器拉取镜像并打包成tar.gz通过sftp传输到准备好的部署服务器,这里使用的版本为aliyun镜像源拉去的latest版本如下[root@VM-12-10-centos~]#dockerimageinspectnextcloud:latest|grep-iversion"Dock......
  • 每日一道算法题之最小生成树之K算法
    最小生成树。有权无向图。把所有点连通起来的最小权重。k算法://Kruskal算法模版(洛谷)//静态空间实现//测试链接:https://www.luogu.com.cn/problem/P3366importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io......
  • 【Azure Batch Account】批处理服务是否可以固定出口访问IP地址呢?
    问题描述使用AzureBatchAccount服务(批处理),所访问的资源受防火墙保护。现在需要把BatchAccount服务池中的实例地址IP加入到防火墙白名单中,但是由于BatchAccount被没有指定的出口访问IP地址,所以需要把BatchAccount服务的全部IP地址加入到白名单中,但是,它的范围的确太多了!如......