两维dp
class Solution {public boolean canPartition(int[] nums) {int n = nums.length;int sum = 0;for(int i=0;i<n;i++){sum+=nums[i];}if(sum%2 != 0)return false;int target = sum/2;boolean[][] dp = new boolean[n][target+1];// 初始化,初始化dp表格的第一行元素dp[0][0] = true;if(nums[0]<=target)dp[0][nums[0]] = true;for(int i=1;i<n;i++){for(int j=0;j<=target;j++){// j<nums[i]的情况,直接把上一行的移动下来dp[i][j] = dp[i-1][j];if(j>=nums[i])dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i]];// System.out.print(dp[i][j]+" ");}// System.out.print("\n");if(dp[i][target]==true)return true;}return false;}
}
降维后
class Solution {public boolean canPartition(int[] nums) {int n = nums.length;int sum = 0;for(int i=0;i<n;i++){sum+=nums[i];}if(sum%2 != 0)return false;int target = sum/2;boolean[] dp = new boolean[target+1];// 初始化dp[0] = true;if(nums[0]<=target)dp[nums[0]] = true; for(int i=1;i<n;i++){for(int j=target;j>=0;j--){// j<nums[i]的情况,直接把上一行的移动下来// dp[i][j] = dp[i-1][j];if(j>=nums[i])dp[j] = dp[j] || dp[j-nums[i]];// System.out.print(dp[j]+" ");}// System.out.print(i+" "+"\n");if(dp[target]==true)return true;}return false;}
}
两维dp:
- i(行)代表第i个物品选不选,j(列)代表容量。
- 先初始化第一行,因为要一行一行地遍历后面的行,后一行要用到前一行的数据。
- 遍历后一行的时候,要不等于前一行的值(不选该物品),要不等于前一行j值减nums[i]的值(选该物品)dp[j] = dp[j] || dp[j-nums[i]]。
降维dp:
因为遍历后一行的数据的时候,只会用到前一行的数据,降维之后,遍历后一行的时候,现在dp上存放的就是前一行的数据,所以直接使用更新就好,前提是倒序更新,因为正序更新会破坏上一行数据的完整性。