416. 分割等和子集
一、题目
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
二、思路
假定nums[]数组下标从1开始,如何确定f[i][j]的值?
我们一般去考虑最后一步,那么对于当前的数字 nums[i],可以选取也可以不选取:
- 1、不选
nums[i],那么我们就从前i - 1个数中选,看是否使得这些数字的和恰好等于j,即f[i][j] = f[i - 1][j]。 - 2、选择
nums[i],在背包可以装下的情况下,那么相应的背包容量就要减去nums[i],f[i][j]的状态就可以从f[i - 1][j - nums[i]]转移过来,即f[i][j] = f[i - 1][j - nums[i]]。
综上,两种情况只要有一个为true,f[i][j]就为true。因此状态转移方程为f[i][j] = f[i - 1][j] | f[i - 1][j - nums[i]]。
三、代码
class Solution { public boolean canPartition(int[] nums) { int n = nums.length, sum = 0; for(int x : nums) sum += x; if(sum % 2 != 0) return false; int m = sum / 2; boolean[][] f = new boolean[n + 1][m + 1]; f[0][0] = true; for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ if(j >= nums[i - 1]) f[i][j] = f[i - 1][j - nums[i - 1]] || f[i - 1][j]; else f[i][j] = f[i - 1][j]; } } return f[n][m]; } }
四、分析
时间复杂度分析: O(n∗m),n是nums数组的大小,m是数组元素和的一半。
空间复杂度分析:O(n∗m)

浙公网安备 33010602011771号