416.分割等和子集
阿新 • • 發佈:2020-11-05
給定一個只包含正整數的非空陣列。是否可以將這個陣列分割成兩個子集,使得兩個子集的元素和相等。
注意:
每個陣列中的元素不會超過 100
陣列的大小不會超過 200
示例 1:
輸入: [1, 5, 11, 5]
輸出: true
解釋: 陣列可以分割成 [1, 5, 5] 和 [11].
示例2:
輸入: [1, 2, 3, 5]
輸出: false
解釋: 陣列不能分割成兩個元素和相等的子集.
思路:
• 動態規劃(0-1 揹包問題);
• 對於每一個硬幣,可以選擇放入或者不放入揹包;
• 詳見:LeetCode詳解連結。
二維陣列空間:
class Solution { publicboolean canPartition(int[] nums) { int n = nums.length, sum = 0; for(int a : nums) sum += a; if(sum % 2 == 1) return false; //奇數直接返回fasle int weight = sum / 2; boolean[][] dp = new boolean[n+1][weight + 1]; for(int i = 0; i <= n; i++) dp[i][0] = true; //第一列置為 truefor(int i = 1; i <= n; i++){ for(int j = 1; j <= weight; j++){ if(j >= nums[i-1]) dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]]; //對於當前的硬幣,選擇加入或者不加入 else dp[i][j] = dp[i-1][j]; } if(dp[i][weight]) returntrue; //滿足條件,提前結束 } return dp[n][weight]; } }
一維壓縮空間:
class Solution { public boolean canPartition(int[] nums) { int n = nums.length, sum = 0; for(int a : nums) sum += a; if(sum % 2 == 1) return false; //奇數直接返回fasle int weight = sum / 2; boolean[] dp = new boolean[weight + 1]; dp[0] = true; //初始置為 true for(int i = 1; i <= n; i++){ for(int j = weight; j > 0; j--){ //從後往前遍歷,防止 nums[i] = 1 時,從前往後都為 true if(j >= nums[i-1]) dp[j] = dp[j] || dp[j-nums[i-1]]; } if(dp[weight]) return true; //滿足條件,提前結束 } return dp[weight]; } }