再学动态规划之 01背包

leetcode: https://leetcode.com/problems/partition-equal-subset-sum/description/
在这里插入图片描述

写了之后,发现这题跟01背包还有点区别。但是写看这个吧。
暴力搜索的方法。就是每个取或者不去。

class Solution(object):
    def getS(self, arr, index, target):
    	if target == 0:
    		return True
    	elif target < 0:
    		return False
    	else:
	        if index == len(arr)-1:
	            if arr[index] == target:
	                return True
	            else:
	                return False
	        else:
	            return self.getS(arr, index+1, target) or self.getS(arr, index+1, target-arr[index])

    def canPartition(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        total = sum(nums)
        if total%2 == 1:
            return False
        target = total/2
        return self.getS(nums, 0, target)

超时是必然的。接下来,我们把目前 考虑index和目标target记录下来:

rec_dict = dict()
class Solution(object):
    def getS(self, arr, index, target):
    	if target == 0:
    		return True
    	elif target < 0:
    		return False
    	else:
			if index == len(arr)-1:
				if arr[index] == target:
					return True
				else:
					return False
			else:
				temp = str(index)+'_'+str(target)
				if temp in rec_dict:
					return rec_dict[str(index)+'_'+str(target)]
				else:
					rec_dict[str(index)+'_'+str(target)] = self.getS(arr, index+1, target) or self.getS(arr, index+1, target-arr[index])
					return rec_dict[str(index)+'_'+str(target)]

    def canPartition(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        rec_dict.clear()
        total = sum(nums)
        if total%2 == 1:
            return False
        target = total/2
        return self.getS(nums, 0, target)

这下通过了。但是我们发现这里 存在众多的递归调用。这就是因为没有按顺序计算的结果。这也引入了动态规划:

class Solution(object):
    def canPartition(self,nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        total = sum(nums)
        if total % 2 == 1:
            return False
        target = total / 2
        arr = [[False for _ in range(target+1)] for _ in range(len(nums)+1)]
        for ix in range(len(arr)):
            arr[ix][0] = True
        for i in range(1, len(nums) + 1):
            for j in range(1, target + 1):
                if j - nums[i - 1] >= 0:
                    arr[i][j] = (arr[i - 1][j - nums[i - 1]] or arr[i - 1][j])
                else:
                    arr[i][j] = arr[i - 1][j]
            if arr[i][target] == True:
                return True
        return False

之前用

arr = [[False]*x]*y

的方式初始化。看似很厉害,其实是错的。 详见:https://www.cnblogs.com/woshare/p/5823303.html



接下来是有趣的解法

class Solution(object):
    def canPartition(self,nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        possible_sum = {0}
        for num in nums:
            possible_sum.update({v+num for v in possible_sum})
        return sum(nums)/2. in possible_sum

意思就是 直接把可能的和加出来。。。。

进阶:bitset! https://www.cnblogs.com/grandyang/p/5951422.html
python没有对应的写法,很让人捉急

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值