474. 一和零

题型描述

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

现在,假设你分别支配着 m0n1。另外,还有一个仅包含 01 字符串的数组。

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

注意:

  1. 给定 01 的数量都不会超过 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” 。

思路:

这是一道典型的0/1背包问题,如果不知道什么0/1背包问题,我们一起学习下!

什么是0/1背包?

问题描述:给你一些商品有重量weights:[2,3,4,5],和对应的价值values:[3,4,5,7],再给你一个只能装9背包,你该如何使你装东西更值钱?一句话说明白:就是这个商品你取与不取!

如何解决?

一般采用是动态规划

weightsvaluesindex\bag_weight0123456789
0000000000000
2310033333333
3420034477777
45300345789912
5740034578101112

理解思路:

  1. 当一件商品不取的时候,背包不管能装多少重量,价值都为0,如图表第一行所示.
  2. 当取第一物品时候,重量为2,价值为3.
    1. 背包可以装0重量时候,可以不行,所以为价值为0
    2. 1也不行,价值为0(因为根本装不下)
    3. 当能装2重量时候,这时候我们就要比较了,就是装与不装,取最大值.简单来说,dp[i][j] = max(dp[i-1][j],dp[i-1][j-weights[i-1]]+values[i-1])这步要认真理解,很重要!最关键的
  3. 下面以此类推,按照上面的动态方程操作

上面写代码时候需要用二维数组,但是我们可以倒着推,只需要一维数组了:

附上代码:

class Solution:
    # 用二维数组
	def knapSack(self, weights, values, bag_weight):
		nums = len(weights)
		dp = [[0] * (bag_weight + 1) for _ in range(nums + 1)]
		# print(dp)
		for i in range(1, nums + 1):
			for j in range(bag_weight+1):
				if j - weights[i - 1] >= 0:
					dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weights[i - 1]] + values[i - 1])
				else:
					dp[i][j] = dp[i - 1][j]
		# print(dp)
		return dp[-1][-1]
	# 用一维数组
	def knapSack1(self, weights, values, bag_weight):
		nums = len(weights)
		dp = [0]*(bag_weight+1)
		for i in range(nums):
			for j in range(bag_weight,-1,-1):
				if j >= weights[i]:
					dp[j] = max(dp[j],dp[j-weights[i]]+values[i])
		return dp[-1]

测试代码:

a = Solution()
print(a.knapSack([3, 4, 5], [4, 5, 6], 10))
print(a.knapSack1([3, 4, 5], [4, 5, 6], 10))

结果:

11

11

完全正确!

所以,理解如何解决0/1背包问题,这道题就非常简单了

此题解决代码:

class Solution(object):
	def findMaxForm(self, strs, m, n):
		"""
		:type strs: List[str]
		:type m: int
		:type n: int
		:rtype: int
		"""
		if not strs:
			return 0
		nums = len(strs)
		dp = [[[0] * (n + 1) for _ in range(m + 1)] for _ in range(nums + 1)]
		# print(dp)
		for i in range(1, nums + 1):
			temp_n = len(strs[i - 1])
			zero_nums = strs[i - 1].count("0")
			one_nums = temp_n - zero_nums
			# print(zero_nums,one_nums)
			for j in range(m+1):
				for k in range(n+1):
					# print(i,k)
					# print(zero_nums,one_nums)
					if j >= zero_nums and k >= one_nums:
						dp[i][j][k] = max(dp[i - 1][j][k], dp[i - 1][j - zero_nums][k - one_nums] + 1)
					else:
						dp[i][j][k] = dp[i - 1][j][k]
					# print(dp)
		return dp[-1][-1][-1]

	def findMaxForm1(self, strs, m, n):
		if not strs:
			return 0
		nums = len(strs)
		dp = [[0] * (n + 1) for _ in range(m + 1)]
		for i in range(nums):
			# 先计算有多少0和1
			zero_nums = 0
			one_nums = 0
			for alp in strs[i]:
				if alp == "0":
					zero_nums += 1
				else:
					one_nums += 1
			for j in range(m,-1,-1):
				for k in range(n,-1,-1):
					if j >= zero_nums and k >= one_nums:
						dp[j][k] = max(dp[j][k],dp[j-zero_nums][k-one_nums]+1)
		# print(dp)
		return dp[-1][-1]

测试代码:

a = Solution()
print(a.findMaxForm(["10", "0001", "111001", "1", "0"], m=5, n=3))
print(a.findMaxForm1(["10", "0001", "111001", "1", "0"], m=5, n=3))

显示结果:

4

4

AC!舒服!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值