1. 程式人生 > >【LeetCode 中等題】75-分割等和子集

【LeetCode 中等題】75-分割等和子集

題目描述:給定一個只包含正整數非空陣列。是否可以將這個陣列分割成兩個子集,使得兩個子集的元素和相等。

注意:

  1. 每個陣列中的元素不會超過 100
  2. 陣列的大小不會超過 200

示例 1:

輸入: [1, 5, 11, 5]

輸出: true

解釋: 陣列可以分割成 [1, 5, 5] 和 [11].

示例 2:

輸入: [1, 2, 3, 5]

輸出: false

解釋: 陣列不能分割成兩個元素和相等的子集.

解法1。這是個典型的揹包問題,能不能找到若干各元素使其和等於sum/2(sum必須是可均分的,不然返回False)。

class Solution(object):
    def canPartition(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        if not nums:
            return False
        summ = sum(nums)
        if summ & 1:
            return False
        memo = [[-1 for _ in range(summ//2+1)] for _ in range(len(nums))]
        return self.helper(nums, 0, summ//2, memo)
    
    def helper(self, nums, index, summ, memo):
        if summ == 0:
            return True    
        if index >= len(nums) or summ < 0:
            return False
        if memo[index][summ] != -1:
            return memo[index][summ] == 1
        if self.helper(nums, index+1, summ, memo) or self.helper(nums, index+1, summ-nums[index], memo):
            memo[index][summ] = 1
        else:
            memo[index][summ] = 0
        return memo[index][summ] == 1

解法2。改寫成DP,自底向上

class Solution(object):
    def canPartition(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        if not nums:
            return False
        summ = sum(nums)
        if summ & 1:
            return False
        memo = [False for _ in range(summ//2+1)]
        c = summ//2
        for i in range(c+1):
            memo[i] = True if nums[0] == i else False
        for i in range(1, len(nums)):
            j=c
            while j >= nums[i]:
                memo[j] = memo[j] or memo[j-nums[i]]
                j -= 1
        return memo[-1]