416-Partition-Equal-Subset-Sum

原题链接

0x0 题目详情

给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200

测试用例:

示例 1: 输入: [1, 5, 11, 5] 输出: true 解释: 数组可以分割成 [1, 5, 5] 和 [11].

示例 2: 输入: [1, 2, 3, 5] 输出: false 解释: 数组不能分割成两个元素和相等的子集.

0x1 解题思路

这道题可以转化为最基础的0-1背包问题。转化后的问题就是使用数组中的值填满容量为sum(nums)/2的背包。

那么我采用的做法时从左向右依次判断每个物品是否放入背包。递归函数返回的是[index,nums.length)能否产生符合要求的放置方案。

0x2 代码实现

递归做法:

class Solution {
    public boolean canPartition(int[] nums) {
        if(nums==null || nums.length==0){
            return false;
        }
        int sum=0;
        for(int i=0;i<nums.length;i++){
            sum+=nums[i];
        }
        if(sum%2!=0){
            return false;
        }
        sum/=2;
        return recur(nums,0,0,sum); 
    }
    //重量从nums中选择
    boolean recur(int[] values,int index,int already,int bag){
        if(already== bag){
            return true;
        }
        if(already>bag){
            return false;
        }
        //虽然重量没超,但是没有数据可选了
        if(index==values.length){
            return false;
        }
        boolean p1=recur(values,index+1,already,bag);
        boolean p2=recur(values,index+1,already+values[index],bag);
        return p1|p2;
    }
}

动态规划:

0x3 课后总结

背包问题还没有系统的学习过,不过我的参考文章是基础班-Code07_Knapsack。

不过一般的做法是:我们可以尝试把当前物品放入背包,但是是否会超重还需要判断递归函数的返回值,下面是一份经典的代码:

Last updated

Was this helpful?