欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-02-03 17:06:34
...

416.分割等和子集

给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意:
每个数组中的元素不会超过 100
数组的大小不会超过 200
示例 1:
输入: [1, 5, 11, 5]
输出: true
解释: 数组可以分割成 [1, 5, 5] 和 [11].
示例 2:
输入: [1, 2, 3, 5]
输出: false
解释: 数组不能分割成两个元素和相等的子集.

首先看到这道题的时候,我也是一点思路都没有。通过看别人(大神)的代码,然后看很长时间。。。思考很长时间,,,才弄懂。我相信时间会证明一切!!!

背包问题:有一个容量为 V 的背包,和一些物品。这些物品分别有两个属性,体积 w 和价值 v,每种物品只有一个。要求用这个背包装下价值尽可能多的物品,求该最大价值,背包可以不被装满。
这个问题可以和背包问题相比,使用动态规划。

思路:

首先,数组可以等分,不能是奇数,只能是偶数,然后sum是数组的元素和。然后每个元素相当于一件物品,sum/2相当于背包的容量。只要背包可以装满,就相当于数组可以等分。
最关键的代码:
len为数组长度,sum为数组元素和。dp[ i ][ j ]的意思是:前i个物品是否可以等于j。(前i个物品可以装入也可以不装入,1,5,11,5其中前三个物品就可以达到1和6)

for(int i=1;i<=len;i++){//每一个元素
            for(int j=1;j<=sum/2;j++){//背包容量
                if(j-nums[i-1]<0){//j不可以装入该物品,则dp[i][j]等于上一个dp的值
                    dp[i][j] = dp[i-1][j];
                }else{//不装入或者装入,有点难解释。。。如果上一层是true,这一层一定是true。。。进入else的时候应该是j==nums[i-1],而且dp[i-1][0]==true。。。希望多读几遍完整代码。。
                    dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]];
                }
            }
        }

动态规划有点难理解,但是只要坚持有就希望,大脑需要不断的强化练习,才能有更深的记忆,我一定不会放弃。
完整代码:

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int len = nums.size();
        if (len == 0) return false;
		int sum = 0;
		for (int n : nums)
			sum += n;
		if (sum % 2 == 1) return false;
        vector<vector<bool>>dp(len+1,vector<bool>(sum/2 + 1,false));
        for(int i=0;i<len+1;i++){
            dp[i][0] = true;
        }
        for(int i=1;i<=len;i++){
            for(int j=1;j<=sum/2;j++){
                if(j-nums[i-1]<0){
                    dp[i][j] = dp[i-1][j];
                }else{
                    dp[i][j] = dp[i-1][j]||dp[i-1][j-nums[i-1]];
                }
            }
        }
        return dp[len][sum/2];
    }
};

一个集坚强与自信于一身的菇凉。