dp专题11 一和零

本文介绍了如何使用二维动态规划解决LeetCode中的一个问题,即在给定字符串集合中,找到满足0的数量不超过m个,1的数量不超过n个的字符串组合,求选取字符串的最大数量。

本题链接:. - 力扣(LeetCode)

题目:

思路:

        由题意,这里有两个特征,要求满足选取的字符串总和中,0的个数和1的个数分别不超过m个0 和 n个 1,问选取的字符串最多有多少个。

        又是典型的背包问题,这里我们选取的个数变成了两个,所以这是个二维dp

其中我们明确一下 dp[ i ][ j ] 的含义是我们选取的字符串数量,即价值为 1 ,将 n 和 m 作为背包容量即可。

代码详解如下:

class Solution {
public:
    inline int findMaxForm(vector<string>& strs, int m, int n) 
{
	vector<vector<int>>dp(101,vector<int>(101,0));	// 根据题目范围开辟极限大小
	
	for(string &i:strs)		// 遍历我们是否要选取的字符串,  
	{
		int one = 0,zero = 0;	// 统计该字符串的 0  和  1  的数量
		for(char &j:i) 
			if(j - '0') ++one;
			else ++zero;
		
		// 遍历 容量
		for(int j = m;j >= zero;--j)
		{
			for(int k = n;k >= one;--k)
			{
				dp[j][k] = max(dp[j][k],dp[j - zero][k - one] + 1);		// 推导判断是否选取
			}
		}
	}
	return dp[m][n];	// 返回选取字符串最多的数量
}
};

最后提交:

在动态规划专题里,滑动窗口计数器是种关键的工具,它借助计数器来记录特定元素在窗口内的出现次数,以此辅助解决问题。以下是对其的详细介绍: ### 原理 滑动窗口计数器的核心原理是运用计数器来记录窗口内特定元素的出现次数。在窗口移动的过程中,动态地更新计数器的值,从而依据计数器的状态来判定窗口是否满足特定条件,进而对窗口进行调整。 ### 示例代码 以“将 x 减到 0 的最小操作数”这问题为例,其解决思路为使用计数器 `count` 记录 0 的个数,同时结合滑动窗口思想来解答: ```cpp class Solution { public: int longestOnes(vector<int>& nums, int k) { // 用 count 记录 0 出现的个数 int count = 0, ret = INT_MIN; for (int left = 0, right = 0; right < nums.size(); right++) { // 进窗口 if (nums[right] == 0) { count++; } // right 位置的 0 超过规定的最大翻转 0 的个数 // 进行出窗口操作 while (count > k) { if (nums[left] == 0) { count--; } left++; } // 更新数据 ret = max(ret, right - left + 1); } return ret == INT_MIN? 0 : ret; } }; ``` 在这段代码中,`count` 作为计数器,用于记录当前窗口内 0 的个数。当 `count` 超出规定的最大翻转 0 的个数 `k` 时,就需要对窗口进行调整,即移动左指针 `left`,同时更新 `count` 的值。 ### 滑动窗口计数器的限制条件 在使用滑动窗口计数器时,需要明确窗口的限制条件。例如,在某些问题中,窗口的限制是当前窗口 `(right - left + 1)` 的非主体元素 `(right - left + 1 - maxn)` 的个数不超过 `k` 个。旦超过这个限制,就需要缩小窗口(`left + 1`) [^2]。 ### 应用场景 滑动窗口计数器在动态规划问题中应用广泛,特别是在处理子数组、子串相关问题时,能够有效地降低时间复杂度。例如,在寻找最长无重复子串的问题中,也可以使用滑动窗口计数器的思想: ```python def length_of_longest_substring(s: str) -> int: # 使用哈希集合记录窗口中的字符 char_set = set() left = 0 max_len = 0 for right in range(len(s)): # 如果当前字符已在集合中,移动左指针 while s[right] in char_set: char_set.remove(s[left]) left += 1 # 添加当前字符到集合 char_set.add(s[right]) # 更新最大长度 max_len = max(max_len, right - left + 1) return max_len ``` 在这个例子中,使用 `char_set` 作为计数器,记录当前窗口内的字符。当遇到重复字符时,移动左指针 `left`,并更新 `char_set`,从而保证窗口内的字符无重复。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值