力扣 416. 分割等和子集 01背包/暴力

https://leetcode-cn.com/problems/partition-equal-subset-sum/
力扣 416. 分割等和子集 01背包/暴力_第1张图片
思路一: d p dp dp,首先计算数组元素的和,如果为奇数则一定不能满足题意,否则子集的和就等于总和的一半,假设为 h a l f half half,那么问题转换成:是否可以从数组中任取一些数字使得它们的和为 h a l f half half 01 01 01背包可解, d p [ i ] = 1 dp[i]=1 dp[i]=1说明可以组成 i i i这个数,否则说明不能组成 i i i这个数,那么对于数组中的每个元素 v v v都有, d p [ i ] = d p [ i − v ] ∣ ∣ d p [ i ] dp[i]=dp[i-v]||dp[i] dp[i]=dp[iv]dp[i],其中 v < = i < = h a l f v<=i<=half v<=i<=half

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum=0;
        for(int i:nums)
            sum+=i;
        if(sum&1)
            return 0;
        if(!sum)
            return 1;
        int half=sum>>1;
        vector<bool> dp(half+1);
        dp[0]=1;
        for(int v:nums){
            for(int i=half;i>=v;i--)
                dp[i]=dp[i]||dp[i-v];
            if(dp[half])
                return 1;
        }
        return 0;
    }
};

思路二:爆搜+剪枝。

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum=0;
        for(int i:nums)
            sum+=i;
        if(sum&1)
            return 0;
        if(!sum)
            return 1;
        return dfs(sum>>1,0,nums);
    }

    bool dfs(int tar,int idx,vector<int>& nums){
        if(!tar)
            return 1;
        int siz=nums.size();
        for(int i=idx;i<siz;i++){
            if(i>idx&&nums[i]==nums[i-1])
                continue;
            if(tar<nums[i])
                return 0;
            if(dfs(tar-nums[i],i+1,nums))
                return 1;
        }
        return 0;
    }
};

你可能感兴趣的:(面试题,背包问题,搜索)