class Solution {
    // 首先想到的是回溯,但是回溯的时间复杂度过大(2^n);
    // 想到背包问题:
    // 两个背包,一个放正数,一个放负数,
    // pos[i] - neg[i] = target;
    // pos[i] + neg[i] = sum;
    // pos[i] = (target + sum) / 2
    public int findTargetSumWays(int[] nums, int target) {
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        //(target + sum)必须是偶数(否则 P 不是整数)
		//(target + sum)不能是负数(否则不可能)
        if ((target + sum) % 2 != 0 || (target + sum) < 0) {
            return 0;
        } 
        int[] pos = new int[(target + sum) / 2 + 1];
        pos[0]= 1; 
        //pos[i] 代表容量为i的背包有多少种方式填满
        for (int i = 0; i < nums.length; i++) {
            for (int j = (target + sum) / 2; j >= nums[i]; j--) {
                pos[j] += pos[j-nums[i]]; 
            }
        }
        return pos[(target + sum) / 2];
    }
}