算法:关于“目标和”

1.添加符号=目标和

法一:递归

class Solution {
    int res = 0;
    public int findTargetSumWays(int[] nums, int S) {
        if(nums.length == 0 || nums == null) return 0;
        dfs(nums,0,0,S);
        return res;
    }
    private void dfs(int[] nums, int st, int sum, int S) {
        if(st == nums.length) {
            if(sum == S ) res++;
            return;
        }
        dfs(nums, st+1, sum+nums[st], S);
        dfs(nums, st+1, sum-nums[st], S);
    }
}

法二:转化成01背包
数组分为取正和取负的两部分
sum_p + (- sum_n) = target
sum_p*2 = target + sum(nums)
sum_p = (target+sum(nums))/2

    public static int findTargetSumWays(int[] nums, int S) {
        int sum = 0;
        for (int num : nums) {
            sum += num;
        }
        if (sum < S || (sum + S) % 2 == 1) {
            return 0;
        }
        int w = (sum + S) / 2;
        int[] dp = new int[w + 1];
        dp[0] = 1;
        for (int num : nums) {
            for (int j = w; j >= num; j--) {
                dp[j] += dp[j - num];
            }
        }
        return dp[w];
    }

2.分割等和的两个子集

// 0-1背包动态规划
class Solution {
    public boolean canPartition(int[] nums) {
        if(nums.length < 2 || nums == null) return false;

        int sum = 0;
        for(int i=0; i<nums.length; i++) {
            sum += nums[i];

        }
        if(sum % 2 != 0) return false;
        sum = sum/2;
        boolean[] dp = new boolean[sum + 1];
        dp[0] = true;
        for (int num : nums) {
            for (int j = sum; j >= num; j--) {
                dp[j] = dp[j] || dp[j - num];
                if(dp[sum]) return true;
            }
        }
        return false;
    }
}
全部评论

相关推荐

秋国🐮🐴:拿到你简历编号然后让你知道世间险恶
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务