474. Ones and Zeroes
DP 01背包问题
思路: For dp[i][j][k], we can get it by fetching the current string i or discarding the current string, which would result in dp[i][j][k] = dp[i-1][j-numOfZero(strs[i])][i-numOfOnes(strs[i])]+1and dp[i][j][k] = dp[i-1][j][k]; We only need to treat the larger one in it as the largest number for dp[i][j][k].
dp[0][j][k] = 0 i指的是第i个,从1开始表示的strs的第0个,dp[i]的i=0是因为要考虑 strs[0] 这个字符串要和不要的情况。如果第0个字符串要的话,即dp[1][j][k] 要用到dp[i-1]=dp[0]=0.
为什么是 max(dp[i-1][j][k], dp[i-1][j-count[0]][k-count[1]]+1) 因为,不要当前的这个字符串,剩下的0,和1 可能可以组成更多的字符串。所以不要当前的字符串可能可以构成更多。
class Solution(object):
def findMaxForm(self, strs, m, n):
dp = [ [[0]*(n+1) for i in xrange(m+1)] for i in xrange(len(strs)+1)]
for i in xrange(len(strs)+1):
if i > 0:
count = self.countZeroOne(strs, i-1)
for j in xrange(m+1):
for k in xrange(n+1):
if i == 0:
dp[i][j][k] = 0
elif j>=count[0] and k>=count[1]:
dp[i][j][k] = max(dp[i-1][j][k], dp[i-1][j-count[0]][k-count[1]]+1)
else:
dp[i][j][k] = dp[i-1][j][k]
return dp[-1][-1][-1]
def countZeroOne(self, strs, index):
s = strs[index]
zero = one = 0
for c in s:
if c == '0':
zero += 1
elif c =='1':
one += 1
return (zero, one)
# For dp[i][j][k], we can get it by fetching the current string i or discarding the current string, which would result in dp[i][j][k] = dp[i-1][j-numOfZero(strs[i])][i-numOfOnes(strs[i])]+1and dp[i][j][k] = dp[i-1][j][k]; We only need to treat the larger one in it as the largest number for dp[i][j][k].
下面这种一样的
416. Partition Equal Subset Sum
class Solution(object):
def canPartition(self, nums):
s = sum(nums)
if s % 2:
return False
target = s / 2
dp = [[0]*(target+1) for j in xrange(len(nums)+1)]
dp[0][0] = 1 # 没有元素构成0 = 1
# dp[i][j] i=0表示的是没有元素,nums[0]的时候i是1,所以i要到len+1
for i in xrange(1, len(nums)+1):
for j in xrange(1, target+1):
if i == 1:
dp[1][j] = 1 if nums[0] == j else 0
continue
if j-nums[i-1]>=0 : # i表示的是 第i-1个元素
dp[i][j] = dp[i-1][j-nums[i-1]] or dp[i-1][j]
else:
dp[i][j] = dp[i-1][j]
return True if dp[len(nums)][target] else False
变形题:
698. Partition to K Equal Sum Subsets
class Solution(object):
def canPartitionKSubsets(self, nums, k):
S = sum(nums)
if S % k or k < 0: return False
visited = {}
target = S / k
def dfs(kk, curSum, startIndex):
if kk == 1: return True
if curSum == target:
return dfs(kk-1, 0, 0)
for i in xrange(startIndex, len(nums)):
v = nums[i]
if not visited.get(i):
visited[i] = True
if dfs(kk, curSum+v, i+1): return True
visited[i] = False
return False
return dfs(k, 0, 0)