分割等和子集(没理解透彻)

发布时间 2023-08-17 21:11:24作者: 网抑云黑胶SVIP用户

给定一个非空的正整数数组 nums ,请判断能否将这些数字分成元素和相等的两部分。

示例 1:

输入:nums = [1,5,11,5]
输出:true
解释:nums 可以分割成 [1, 5, 5] 和 [11] 。
示例 2:

输入:nums = [1,2,3,5]
输出:false
解释:nums 不可以分为和相等的两部分

背包问题解决

class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0,maxNum = 0;
        //当列表的总和不是偶数,那么不能分为两半
        for(int num : nums){
            sum += num;
            maxNum = Math.max(maxNum,num);
        }
        if(sum % 2 == 1){
            return false;
        }
        //如果其中一个数超了一半,那么这个列表也不能分为两半
        int target = sum / 2;
        if(maxNum>target)return false;
        //背包问题 1,2,3,6为例子
        //  0,1,2,3,4,5,6(总和)
        //0 0,1,0,0,0,0,0
        //1 0,1,1,1,0,0,0
        //2 0,1,1,1,1,1,1
        //3 0,1,1,1,1,1,1
        boolean[][] dp = new boolean[nums.length][target+1];
        for(int i=0;i<nums.length;i++){
            dp[i][0] = false;
        }
        //第一行只有一个满足总和
        dp[0][nums[0]] = true;
        for(int i=1;i<nums.length;i++){
            for(int j=1;j<=target;j++){
                //但总和大于遍历到的数字时,那么就可以取当前遍历的数字
                if(j>=nums[i]){
                    dp[i][j] = dp[i-1][j] | dp[i-1][j-nums[i]];
                }else{
                    dp[i][j] = dp[i-1][j];
                }
            }
        }
        return dp[nums.length-1][target];
    }
}