Leetcode-416.分割等和子集

題目描述

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

注意:

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

示例 1:

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

輸出: true

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

示例 2:

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

輸出: false

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

分析

這道題其實可以變成是0-1揹包問題,利用動態規劃思想做題:

  • 狀態表示:F(n,C)F(n,C),表示前n個數,是否能找到和爲C的數字組合,能爲True,不能爲False
    • 如果不考慮第n個元素,那麼情況等於前n-1個元素的情況即F(n1,C)F(n-1,C)
    • 如果考慮第n個元素,那麼情況等於前n-1個元素的子集和加上第n個元素的和可以組成和C,C-nums[n]表示前n-1個元素可以組成和爲C-nums[n],那麼加上第n個元素nums[n],和即可C,可以組成子集。
  • 狀態轉移公式:F(n,C)=F(n1,C)  or  F(n1,Cnums(i))F(n,C)=F(n−1,C) ~~or~~ F(n−1,C−nums(i))
  • 邊界:0邊界爲 FalseFalse

代碼

class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        sumNums = sum(nums)
        
        if sumNums%2==1:
            return False

        sumOfHalf = sumNums//2


        length = len(nums)
        dp = [[False for i in range(sumOfHalf+1)] for j in range(length+1)]
        for i in range(length+1):
            dp[i][0] = True

        for i in range(1, length+1):
            for j in range(1, int(sumOfHalf)+1):
                dp[i][j] = dp[i-1][j]
                if j>=nums[i-1]:
                    dp[i][j] = dp[i][j] or dp[i-1][j-nums[i-1]]
        
        return dp[length][sumOfHalf]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章