【开始刷LeetCode】474. 一和零

本文介绍了如何使用动态规划解决LeetCode中的474题,该题要求找到二进制字符串数组中,最大子集的长度,该子集中最多包含m个0和n个1。通过对比01背包问题,建立三维动态规划模型,最终优化为二维空间的解决方案。 AC代码展示了具体的实现过程。

一、绪

本篇文章主要用到动态规划的思想,并且这个问题和动态规划中经典的01背包问题类似,所以我们可以套用01背包的解法求解这个问题。但这个问题要比基本的01背包要复杂一点,原来的01背包只需要考虑重量一个限制因素,而这道题需要考虑两个限制因素。

01背包的问题解法我也在另外一篇博客里进行了分析解释,详情可跳转链接: 【动态规划】01背包问题(装还是不装,老子不装啦。。。老子就是菜).

二、一和零

链接: 474. 一和零.

(一)题目描述

解释
给你一个二进制字符串数组 strs 和两个整数 m 和 n 。
请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。
如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

示例一:

输入: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 。

示例二:

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

解题思路
如果对经典01背包问题有认知,那么这道题与01背包问题的区别就是比01背包只需要考虑重量这一限制元素要多一个限制元素。打个比喻,01背包原本只需要考虑物品的重量,现在我要同时考虑物品的重量和体积。

所以我们解决问题就需要用到一个三维数组,利用01背包解决问题的算法思想我们就能解决这个问题。
在这里插入图片描述
算法公式如下:
在这里插入图片描述

(二)AC代码

以下的代码,我是优化了空间的,只用二维的dp数组。

int findMaxForm(char ** strs, int strsSize, int m, int n){

    int Wm[strsSize],Wn[strsSize];

    for(int i=0;i<strsSize;i++){
        int ones=0,zeroes=0;
        for(int j=0;j<strlen(strs[i]);j++){
            if(strs[i][j]=='1'){
                ones++;
            }else{
                zeroes++;
            }
        }
        Wm[i]=zeroes;
        Wn[i]=ones;
    }

    int dp[m+1][n+1];
    memset(dp,0,sizeof(dp));

    for(int k=0;k<strsSize;k++){
        for(int i=m;i>=0;i--){
            for(int j=n;j>=0;j--){
                if(i>=Wm[k]&&j>=Wn[k]){
                    if(dp[i][j]<dp[i-Wm[k]][j-Wn[k]]+1){
                        dp[i][j]=dp[i-Wm[k]][j-Wn[k]]+1;
                    }
                }
            }
        }
    }

    return dp[m][n];
}
### 如何使用 C++ 从开始高效 LeetCode 题目 #### 初步准备 为了能够顺利地利用 C++ 进行 LeetCode 的练习,首先需要完成注册与登录操作[^1]。这步骤是进入平台并解锁其功能的基础。 #### 学习基础语法 熟悉 C++ 基础语法对于解决算法问题是至关重要的。可以通过编写简单的程序来掌握基本的数据结构控制流语句。例如,在处理优先队列时可以参考如下代码片段: ```cpp #include <iostream> #include <queue> int main() { std::priority_queue<int, std::vector<int>, std::greater<>> q; // 小顶堆定义 q.push(9); q.push(-1); q.push(8); while (!q.empty()) { std::cout << q.top() << " "; q.pop(); } } ``` 上述代码展示了如何通过 `std::greater` `std::less` 来分别创建小顶堆大顶堆[^2]。 #### 掌握核心数据结构与算法 LeetCode 上的许多题目都涉及常见的数据结构算法设计模式。比如动态规划种非常有效的解决问题的方法之。在某些情况下,可能需要用动态规划的思想求解最优子结构性质的问题。例如,“买卖股票的最佳时机”问题可以用以下方式实现[^3]: ```cpp class Solution { public: int maxProfit(vector<int>& prices) { if (prices.size() == 0) return 0; int minPrice = INT_MAX; int maxProfit = 0; for(auto price : prices){ if(price < minPrice) minPrice = price; else if((price - minPrice) > maxProfit) maxProfit = price - minPrice; } return maxProfit; } }; ``` #### 动态规划的应用实例 当遇到更复杂的优化类问题时,如硬币找问题,则需深入理解动态规划的核心概念及其应用方法。具体来说,这类问题通常涉及到状态转移方程的设计以及边界条件的设定。以下是基于完全背包模型的个解决方案示例[^4]: ```cpp const static int INF = 0x3f3f3f3f; class Solution { public: int coinChange(vector<int> &coins, int amount) { vector<int> dp(amount + 1, INF); dp[0] = 0; for(int i=0;i<coins.size();i++) { for(int j=coins[i];j<=amount;j++) { if(dp[j-coins[i]] != INF){ dp[j] = min(dp[j], dp[j-coins[i]]+1); } } } return dp[amount]==INF ? -1 : dp[amount]; } }; ``` #### 记录与总结 持续记录个人的学习过程非常重要。即使不详尽解释每道题目的解答逻辑,也应保存已完成的任务列表以便后续复习巩固所学知识[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ヌヌ イホ キT エ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值