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]]

综上,两种情况只要有一个为truef[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)nnums数组的大小,m是数组元素和的一半。

空间复杂度分析:O(n∗m)

posted @ 2023-04-24 11:12  ImreW  阅读(23)  评论(0)    收藏  举报