算法——利用数组内所有元素进行加或者减以达到目标和

给定一个非负整数数组,a1, a2, …, an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。
返回可以使最终数组和为目标数 S 的所有添加符号的方法数。
leetcode

解题思路:

  • 首先想到的是暴力深搜,枚举每一种做法,这样时间复杂度是n方的,也没有什么意义。
  • 可以采用动态规划的思想。设负数和为y,正数和为x,则有 x + y = S,还有x - y = sum,sum是数组中所有元素的累加。这样可以得到 x = (S + sum) / 2,于是将问题转化为了一个01背包问题。
class Solution {
    public int findTargetSumWays(int[] nums, int s) {
        int sum = 0;

        for(int n : nums) sum += n;

		// 因为不存在小数,正数和一定是偶数,所以,如果是奇数就直接返回0
        if((sum + s) % 2 == 1) return 0;
        
        // 全部都为正数还每目标值大,那就没必要算了
        if(s > sum) return 0;

        int len = (sum + s) / 2;
        int[] f = new int[len + 1];
        f[0] = 1;

		// 01背包,先枚举物品,再从高到底枚举和
        for(int n : nums) {
            for(int i = len; i >= n; i--) {
                f[i] += f[i - n];
            }
        }

        return f[len];
    }
}
原文地址:https://www.cnblogs.com/lippon/p/14117612.html