LeetCode DP篇-揹包問題(416)
阿新 • • 發佈:2020-08-28
416. 分割等和子集
給定一個只包含正整數的非空陣列。是否可以將這個陣列分割成兩個子集,使得兩個子集的元素和相等。
注意:
每個陣列中的元素不會超過 100
陣列的大小不會超過 200
示例 1:
輸入: [1, 5, 11, 5]
輸出: true
解釋: 陣列可以分割成 [1, 5, 5] 和 [11].
示例 2:
輸入: [1, 2, 3, 5]
輸出: false
解釋: 陣列不能分割成兩個元素和相等的子集.
solution 1 二維陣列
class Solution { public boolean canPartition(int[] nums) { int sum = 0; for(int i = 0; i < nums.length; i++){ sum += nums[i]; } //和為奇數,不可能存在 if (sum%2 != 0) return false; sum /= 2; //預設為false boolean[][] dp = new boolean[nums.length+1][sum+1]; //base case for(int i = 0; i < nums.length+1; i++){ dp[i][0] = true; } //狀態轉移方程 for (int i = 1; i < nums.length+1; i++){ for (int j = 1; j < sum+1; j++){ //剩下空間裝不下,不裝入 if (j-nums[i-1] < 0){ dp[i][j] = dp[i-1][j]; }else{ //剩下空間可裝入的情況下,裝入後剩下為0,即為true dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]]; } } } return dp[nums.length][sum]; } } //分成兩個和相等的子集,等於找到和為總數和二分之一的陣列,即0-1揹包問題
solution2 一維陣列
class Solution { public boolean canPartition(int[] nums) { int sum = 0; for(int i = 0; i < nums.length; i++){ sum += nums[i]; } //和為奇數,不可能存在 if (sum%2 != 0) return false; sum /= 2; //預設為false 每一次只依靠nums陣列的前一個 boolean[] dp = new boolean[sum+1]; //base case dp[0] = true; //狀態轉移方程 for (int i = 0; i < nums.length; i++){ for (int j = sum; j >= 0; j--){ //剩下空間可裝入時 if (j-nums[i] >= 0){ dp[j] = dp[j] || dp[j-nums[i]]; } } } return dp[sum]; } }