leetcode416分割等和子集——又一個揹包問題
阿新 • • 發佈:2019-01-03
題目:
給定一個只包含正整數的非空陣列。是否可以將這個陣列分割成兩個子集,使得兩個子集的元素和相等。
注意:
- 每個陣列中的元素不會超過 100
- 陣列的大小不會超過 200
示例 1:
輸入: [1, 5, 11, 5] 輸出: true 解釋: 陣列可以分割成 [1, 5, 5] 和 [11].
首先可以看出如果陣列和為奇數,是無法分割的(自然數乘以二都是偶數)。
然後其中一個基本想法是BFS,這個數字nums【i】我可以選擇“加上”或者“不加”,
也就是雙重遞迴。
思路如下:
def canPartition_(self, nums): """ :type nums: List[int] :rtype: bool """ nums_sum=sum(nums) if nums_sum%2!=0: return False else: nums_sum//=2 rec=[False] def search(nums,i,s=0): if i==len(nums) or s>nums_sum: return if nums[i]+s==nums_sum: rec[0]=True return else: search(nums,i+1,s) search(nums,i+1,s+nums[i]) search(nums,0,0) return rec[0]
很可惜,這個方法只能AC不到一半的測試用例(可能C++或者Java會更多吧,畢竟沒有遞迴限制)。
那麼參考別人的答案後發現了用揹包問題來解決的辦法。
實際上我也想到過,但是無法轉化成對應程式碼。
def canPartition(self,nums): nums_sum = sum(nums) if nums_sum % 2 != 0: return False else: nums_sum //= 2 dp=[[0 for x in range(nums_sum+1)] for y in range(len(nums))] for i in range(nums[0],len(dp[0])): dp[0][i]=nums[0] for i in range(1,len(nums)): for j in range(nums[i],nums_sum+1): dp[i][j]=max(dp[i-1][j],dp[i-1][j-nums[i]]+nums[i]) return dp[-1][-1]==nums_sum
然而這個程式碼沒有通過,哈哈哈哈。
因為python太慢了,而我參考的java程式碼(寫法幾乎一樣)是可以通過的。
對於這種可以轉化為揹包問題的問題,還需要多加練習。