算法课第8周第1题——494. Target Sum

来源:互联网 发布:csgo awp 数据 编辑:程序博客网 时间:2024/06/05 07:48

题目描述:

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: 5Explanation: -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 = 3There 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.
程序代码:

class Solution {public:int findTargetSumWays(vector<int>& nums, int S) {// 所有数组中数的总和为sumint sum = 0;for (int i = 0; i < nums.size(); i++) {sum += nums[i];}if (S < -sum || S > sum) {return 0;}// 用一个map(名为dp)来进行动态规划// dp[i]表示运算结果为i的取法数(i值可取正、0、负)。dp[S]即是最终答案map<int, int> dp;for (int i = -sum; i <= sum; i++) {dp[i] = 0;}// 当开始循环前,还没有数能遍历,此时S=0的取法数为1dp[0] = 1;// 外层循环,使内层第1次访问num[0](即输入的第一个数), 第2次访问num[1]....第n次访问num[n-1]for (int i = 0; i < nums.size(); i++) {// temp用于暂时存放,每次外层循环最后会将temp赋给dpmap<int, int> temp;for (int t = -sum; t <= sum; t++) {temp[t] = 0;}// 内层循环。将所有dp的值更新。// 只要j的值不超过[-sum, sum]的范围,或dp[j]不为0(dp[j]为0时不计算,节约时间)// 就可用动态规划计算for (int j = -sum; j <= sum; j++) {if (dp[j] != 0 && j - nums[i] >= -sum && j + nums[i] <= sum) {temp[j - nums[i]] += dp[j];temp[j + nums[i]] += dp[j];}}dp = temp;}return dp[S];}};

简要题解:

本题用到了动态规划的思想。

先理解题意。本题输入为一组整数,通过给这组整数添加+ 或 -,可以运算出一个结果。 求使得最终运算结果为S的取法数。

令sum为输入数组里数字的总和,设dp[i]为结果为i 时的取法数。则i 的取值范围是[-sum, sum]. dp[0]初始化为1, 表示还未开始对输入数组num循环前,结果为0的取法有1种(因为没开始对num循环,所以没有取数,所以最终结果自然就是0)。其余dp的值初始化为0.

接着开始对输入数组num循环(外层循环),使得内层第1次访问num[0] (即输入的第一个数), 第2次访问num[1]....第n次访问num[n-1]

而内层循环则每次都从-sum到sum遍历dp(即遍历dp的所有值)并更新dp的值。用于循环的变量j 正是某几个数的加减计算结果值(所以取值范围才是[-sum, sum])。当访问到num[i]时,由于接下来要减去或加上num[i], 因此会影响dp[j - nums[i]] 和 dp[j + nums[i]]的值(即运算结果为j - nums[i]或 j + nums[i] 时的取法数),因此由动态规划可推得:

dp[j - nums[i]] = dp[j - nums[i]] + dp[j]


dp[j + nums[i]] = dp[j+nums[i]] + dp[j]


这样经过两层的循环,就可以不断更新并得到最终的dp.  而dp[S]正是最终的输出结果(运算结果为S时的取法数)。

本题属于有一些难度的动态规划,我思考的时候花了不少力气,不过理清思路后代码写起来倒还相对容易。动态规划就属于思考起来比较难的题目,要花不少脑筋去想,我感觉自己目前还不够熟练。之后有机会我还会做更多训练。

0 0