You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol.

Find out how many ways to assign symbols to make sum of integers equal to target S.

Example 1:

Input: nums is [1, 1, 1, 1, 1], S is 3.
Output: 5
Explanation: -1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3 There are 5 ways to assign symbols to make the sum of nums be target 3.

Note:

    1. The length of the given array is positive and will not exceed 20.
    2. The sum of elements in the given array will not exceed 1000.
    3. Your output answer is guaranteed to be fitted in a 32-bit integer.

这道题给了我们一个数组,和一个目标值,让给数组中每个数字加上正号或负号,然后求和要和目标值相等,求有多少中不同的情况。那么对于这种求多种情况的问题,博主最想到的方法使用递归来做。从第一个数字,调用递归函数,在递归函数中,分别对目标值进行加上当前数字调用递归,和减去当前数字调用递归,这样会涵盖所有情况,并且当所有数字遍历完成后,若目标值为0了,则结果 res 自增1,参见代码如下:

解法一:

class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int res = ;
helper(nums, S, , res);
return res;
}
void helper(vector<int>& nums, long S, int start, int& res) {
if (start >= nums.size()) {
if (S == ) ++res;
return;
}
helper(nums, S - nums[start], start + , res);
helper(nums, S + nums[start], start + , res);
}
};

我们对上面的递归方法进行优化,使用 memo 数组来记录中间值,这样可以避免重复运算,参见代码如下:

解法二:

class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
vector<unordered_map<int, int>> memo(nums.size());
return helper(nums, S, , memo);
}
int helper(vector<int>& nums, long sum, int start, vector<unordered_map<int, int>>& memo) {
if (start == nums.size()) return sum == ;
if (memo[start].count(sum)) return memo[start][sum];
int cnt1 = helper(nums, sum - nums[start], start + , memo);
int cnt2 = helper(nums, sum + nums[start], start + , memo);
return memo[start][sum] = cnt1 + cnt2;
}
};

我们也可以使用迭代的方法来解,使用一个 dp 数组,其中 dp[i][j] 表示到第 i-1 个数字且和为j的情况总数,参见代码如下:

解法三:

class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int n = nums.size();
vector<unordered_map<int, int>> dp(n + );
dp[][] = ;
for (int i = ; i < n; ++i) {
for (auto &a : dp[i]) {
int sum = a.first, cnt = a.second;
dp[i + ][sum + nums[i]] += cnt;
dp[i + ][sum - nums[i]] += cnt;
}
}
return dp[n][S];
}
};

我们也可以对上面的方法进行空间上的优化,只用一个 HashMap,而不是用一个数组的哈希表,在遍历数组中的每一个数字时,新建一个 HashMap,在遍历原 HashMap 中的项时更新这个新建的 HashMap,最后把新建的 HashMap 整个赋值为原 HashMap,参见代码如下:

解法四:

class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
unordered_map<int, int> dp;
dp[] = ;
for (int num : nums) {
unordered_map<int, int> t;
for (auto a : dp) {
int sum = a.first, cnt = a.second;
t[sum + num] += cnt;
t[sum - num] += cnt;
}
dp = t;
}
return dp[S];
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/494

类似题目:

Expression Add Operators

参考资料:

https://leetcode.com/problems/target-sum/

https://leetcode.com/problems/target-sum/discuss/97371/Java-Short-DFS-Solution

https://leetcode.com/problems/target-sum/discuss/97369/Evolve-from-brute-force-to-dp

https://leetcode.com/problems/target-sum/discuss/97334/Java-(15-ms)-C%2B%2B-(3-ms)-O(ns)-iterative-DP-solution-using-subset-sum-with-explanation

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Target Sum 目标和的更多相关文章

  1. LeetCode Target Sum

    原题链接在这里:https://leetcode.com/problems/target-sum/description/ 题目: You are given a list of non-negati ...

  2. [LeetCode] 494. Target Sum 目标和

    You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symb ...

  3. 494 Target Sum 目标和

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

  4. Leetcode——Target Sum

    Question You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you ha ...

  5. Leetcode之深度优先搜索(DFS)专题-494. 目标和(Target Sum)

    Leetcode之深度优先搜索(DFS)专题-494. 目标和(Target Sum) 深度优先搜索的解题详细介绍,点击 给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S.现在 ...

  6. [Leetcode] DP -- Target Sum

    You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symb ...

  7. LN : leetcode 494 Target Sum

    lc 494 Target Sum 494 Target Sum You are given a list of non-negative integers, a1, a2, ..., an, and ...

  8. 59.Target Sum(目标和)

    Level:   Medium 题目描述: You are given a list of non-negative integers, a1, a2, ..., an, and a target, ...

  9. Longest subarray of target sum

    2018-07-08 13:24:31 一.525. Contiguous Array 问题描述: 问题求解: 我们都知道对于subarray的问题,暴力求解的时间复杂度为O(n ^ 2),问题规模已 ...

随机推荐

  1. Android类参考---SQLiteOpenHelper

    public 抽象类 SQLiteOpenHelper 继承关系 java.lang.Object |____android.database.sqlite.SQLiteOpenHelper 类概要 ...

  2. 使用Listview控件显示数据

    1.图像列表控件 ImageList是含有图像对象的集合,可以通过索引或关键字引用该集合中的每个对象. ImageList空间的属性 属性 说明 Images 存储在图像列表中的所有图像 ImageS ...

  3. Object类-----java

    Object类是所有类的父类,如果一个类没有使用extends关键字明确标识继承另一个类,那么这类默认继承object类 Object类中的方法,适合所有子类. 1 toString()方法在Obje ...

  4. JAVA-基础语法篇

    JAVA-基础语法篇 一.     基础语法: 对大小写敏感 类名的首字母大写 方法名首字母小写,后面用驼峰发命名 源文件名和类名要相同 主方法入口: public static void main( ...

  5. XMAN-level4

    [XMAN] level4 首先checksec,信息如下 [*] '/root/Desktop/bin/pwn/xman-level4/level4' Arch: i386-32-little RE ...

  6. nodejs安装和卸载

    Ubuntu 上安装 Node.js 方式一:直接安装    一.安装 1.$ sudo apt-get install nodejs2.$ sudo apt-get install npm二.升级 ...

  7. [W班]第二次结对作业成绩评价

    作业地址: https://edu.cnblogs.com/campus/fzu/FZUSoftwareEngineering1715W/homework/1016 作业要求: 1.代码具有规范性. ...

  8. 听翁恺老师mooc笔记(6)--指针运算

    指针值加1就是将指针值加上sizeof(指针所指变量的类型) 1+1=2,那么指针加1是加上了1这个数字吗?试一下,在代码中定义了char数组,char也是整数,数组名是ac,ac中有10个元素,0- ...

  9. sql with as 用法-Z

    以下内容转自:http:.com/ 一.WITH AS的含义 WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个 ...

  10. tornado httpserver

    # coding:utf-8 import tornado.web import tornado.ioloop import tornado.httpserver # 新引入httpserver模块 ...