leetcode刷题笔记-0-1knapsack背包问题

474. Ones and Zeroes 

DP 01背包问题

leetcode刷题笔记-0-1knapsack背包问题_第1张图片

思路: 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].

下面这种一样的

leetcode刷题笔记-0-1knapsack背包问题_第2张图片

 leetcode刷题笔记-0-1knapsack背包问题_第3张图片

416. Partition Equal Subset Sum 

 leetcode刷题笔记-0-1knapsack背包问题_第4张图片

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 

leetcode刷题笔记-0-1knapsack背包问题_第5张图片

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)

 

你可能感兴趣的:(Algorithm)