题目描述:
class Solution {
public boolean canPartition(int[] nums) {
//先求和,然后分成两半
// sum/2看成是一个背包,能正好装满说明可以分成两个相等的子集
// 实际上也是一个动态规划的问题:背包
int sum = 0;
int n = nums.length;
for (int i = 0; i < n; i++) {
sum += nums[i];
}
//如果是奇数,返回false
if (sum % 2 != 0) {
return false;
}
//sum除以2
sum /= 2;
//两个状态:i:前i个数字 j:和为j
//要求的即dp[N][sum/2] 为true即正好装满
boolean[][] dp = new boolean[n + 1][sum + 1];
//base case
for (int i = 0; i < n + 1; i++) {
dp[i][0] = true;//目标为0,那就是装满了
}
//从下标1开始 表示前1个数字
for (int i = 1; i <= n; i++) {
//状态:和的下标0已经设为true了
for (int j = 1; j <= sum; j++) {
if(j-nums[i-1]<0){
//背包装不下
dp[i][j]=dp[i-1][j];//不装
}else {
//装or不装 两种情况 存不存在其中一种可以装满?
dp[i][j]=dp[i-1][j] //不装,取决于上个状态dp[i-1][j]
|| dp[i-1][j-nums[i-1]]; //装,取决于上个状态dp[i-1][j-nums[i-1]]
}
}
}
return dp[n][sum];
}
}