【LeetCode】416. Partition Equal Subset Sum

416. Partition Equal Subset Sum

Description:

Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.

Note:

  1. Each of the array element will not exceed 100.
  2. The array size will not exceed 200.

Example 1:

Input: [1, 5, 11, 5]

Output: true

Explanation: The array can be partitioned as [1, 5, 5] and [11].

Example 2:

Input: [1, 2, 3, 5]

Output: false

Explanation: The array cannot be partitioned into equal sum subsets.

 题目中文描述:

【LeetCode】416. Partition Equal Subset Sum_第1张图片

解题思路:

【LeetCode】416. Partition Equal Subset Sum_第2张图片

注意题目中的限制:

【LeetCode】416. Partition Equal Subset Sum_第3张图片

 题目中的限制条件可以帮助我们判断设计的算法的可行性和有效性。

每个数字的最大值决定了我们背包的容量,进而决定了我们算法的复杂度。

(1)递归法

在LeetCode中“Time Limit Exceeded”不能通过

class Solution:

    def canPartition(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        num_sum = 0
        for i in range(len(nums)):
            num_sum += nums[i]

        if num_sum % 2 != 0:
            return False

        return self.tryPartition(nums, len(nums)-1, num_sum/2)

    def tryPartition(self, nums, index, _sum):
        if _sum == 0:
            return True

        if _sum < 0 or index < 0:
            return False

        return self.tryPartition(nums, index-1, _sum) or \
               self.tryPartition(nums, index-1, _sum-nums[index])

solution = Solution()
# test1
# nums = [1, 5, 11, 5]
# test2
nums = [1, 2, 3, 5]
print(solution.canPartition(nums))

(2)记忆化搜索

在LeetCode中可以AC

class Solution:

    def canPartition(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        num_sum = 0
        for i in range(len(nums)):
            num_sum += nums[i]

        if num_sum % 2 != 0:
            return False

        # memo[i][c]表示使用索引为[0...i]的这些元素是否可以完全填充一个容量为c的背包
        # -1表示为未计算;0表示不可以填充;1表示可以填充
        memo = [[-1] * (int(num_sum / 2) + 1) for _ in range(len(nums))]

        def tryPartition(nums, index, _sum):
            if _sum == 0:
                return True

            if _sum < 0 or index < 0:
                return False

            if memo[index][_sum] != -1:
                return memo[index][_sum] == 1

            memo[index][_sum] = 1 if (tryPartition(nums, index - 1, _sum) or tryPartition(nums, index - 1, _sum - nums[index])) else 0

            return memo[index][_sum] == 1

        return tryPartition(nums, len(nums)-1, int(num_sum / 2))

solution = Solution()
# test1
# nums = [1, 5, 11, 5]
# test2
nums = [1, 2, 3, 5]
print(solution.canPartition(nums))

(3)动态规划解法

使用优化后的动态规划解法,详细介绍文章《动态规划学习-【0-1背包问题的优化和变种】》

已经AC的代码:

class Solution:

    def canPartition(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        num_sum = 0
        for i in range(len(nums)):
            num_sum += nums[i]

        if num_sum % 2 != 0:
            return False

        n = len(nums)
        C = int(num_sum / 2)
        memo = [False] * (C + 1)

        for i in range(C + 1):
            memo[i] = (nums[0] == i)

        for i in range(1, n):
            for j in range(C, nums[i], -1):
                memo[j] = memo[j] or memo[j - nums[i]]

        return memo[C]

solution = Solution()
# test1
# nums = [1, 5, 11, 5]
# test2
# nums = [1, 2, 3, 5]
# test3
nums = [1, 2, 5]
print(solution.canPartition(nums))

 

你可能感兴趣的:(算法,LeetCode)