作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/target-sum/description/

题目描述

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.

题目大意

给了一个数组和一个target number,现在要给这个数组的每个数添加上+或-, 使得求和的结果是target number。求满足条件的组合个数。

解题方法

动态规划

这个题让我扔了三个月,今天又看了两个小时,动态规划不很懂就是这个后果!

刚开始用的dfs做的,遍历所有的结果,统计满足结果的个数就可以了。没错,超时了。超时的代码如下:

class Solution(object):
def findTargetSumWays(self, nums, S):
"""
:type nums: List[int]
:type S: int
:rtype: int
"""
def helper(index, acc):
if index == len(nums):
if acc == S:
return 1
else:
return 0
return helper(index + 1, acc + nums[index]) + helper(index + 1, acc - nums[index])
return helper(0, 0)

其实一般能用dfs解决的题目,如果题目只要求满足条件的数字而不是所有的结果,那么dfs会超时。解决方法其实基本只有一条路:动态规划。

我们定义了一个二维数组,这个二维数组dp[i][j]的意义是我们从最开始的位置到第i个位置上能够成和为j的组合有多少种,因为求和之后数的范围不确定,所以数组中保存的是字典,字典保存的是到i位置能求得的和为某个数的个数。

所以从左到右进行遍历,在每个位置都把前一个位置的字典拿出来,看前一个位置的所有能求得的和。和当前的数值分别进行加减操作,就能得出新一个位置能求得的和了。

状态转移方程是:

dp[0][0] = 1;
dp[i + 1][x + nums[i]] += dp[i][x];
dp[i + 1][x - nums[i]] += dp[i][x];
注意:其中x是在前一个位置能够成的和。

要注意一点是,dp初始不能采用下面方式:

dp = [collections.defaultdict(int)] * (_len + 1)

这种初始化方式会使每个位置的元素其实是同一个字典。

代码如下:

class Solution:
def findTargetSumWays(self, nums, S):
"""
:type nums: List[int]
:type S: int
:rtype: int
"""
_len = len(nums)
dp = [collections.defaultdict(int) for _ in range(_len + 1)]
dp[0][0] = 1
for i, num in enumerate(nums):
for sum, cnt in dp[i].items():
dp[i + 1][sum + num] += cnt
dp[i + 1][sum - num] += cnt
return dp[_len][S]

这个题的C++代码如下,这里的代码说明了对于unordered_map,在C++里面调用一个不存在的key的时候,会使用默认初始化的版本,类似于Python的collections.defaultdict()。比如这里调用的+=符号,在左侧不存在的时候,会初始化0。

class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
const int N = nums.size();
vector<unordered_map<int, int>> dp(N + 1);
dp[0][0] = 1;
for (int i = 0; i < N; i ++) {
for (auto m : dp[i]) {
dp[i + 1][m.first + nums[i]] += m.second;
dp[i + 1][m.first - nums[i]] += m.second;
}
}
return dp[N][S];
}
};

日期

2018 年 5 月 28 日 —— 太阳真的像日光灯~
2018 年 12 月 31 日 —— 2018年最后一天!

【LeetCode】494. Target Sum 解题报告(Python & C++)的更多相关文章

  1. LeetCode 1 Two Sum 解题报告

    LeetCode 1 Two Sum 解题报告 偶然间听见leetcode这个平台,这里面题量也不是很多200多题,打算平时有空在研究生期间就刷完,跟跟多的练习算法的人进行交流思想,一定的ACM算法积 ...

  2. 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 ...

  3. [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 ...

  4. Leetcode 494 Target Sum 动态规划 背包+滚动数据

    这是一道水题,作为没有货的水货楼主如是说. 题意:已知一个数组nums {a1,a2,a3,.....,an}(其中0<ai <=1000(1<=k<=n, n<=20) ...

  5. LeetCode: Minimum Path Sum 解题报告

    Minimum Path Sum Given a m x n grid filled with non-negative numbers, find a path from top left to b ...

  6. 【LeetCode】120. Triangle 解题报告(Python)

    [LeetCode]120. Triangle 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址htt ...

  7. LeetCode 2 Add Two Sum 解题报告

    LeetCode 2 Add Two Sum 解题报告 LeetCode第二题 Add Two Sum 首先我们看题目要求: You are given two linked lists repres ...

  8. 【LeetCode】Permutations II 解题报告

    [题目] Given a collection of numbers that might contain duplicates, return all possible unique permuta ...

  9. 【LeetCode】Island Perimeter 解题报告

    [LeetCode]Island Perimeter 解题报告 [LeetCode] https://leetcode.com/problems/island-perimeter/ Total Acc ...

随机推荐

  1. GeckoDriver的安装和使用

    GeckoDriver用于驱动Firefox,在这之前请确保已经正确安装好了Firefox浏览器并可以正常运行. 一.GeckoDriver的安装 GitHub:https://github.com/ ...

  2. OpenStack——云平台部署

    一.配置网络 准备:安装两台最小化的CentOS7.2的虚拟机,分别添加两张网卡,分别为仅主机模式和NAT模式,并且计算节点设置为4G运行内存,50G硬盘 1.控制节点--配置网络 控制节点第一个网卡 ...

  3. Redis - 1 - linux中使用docker-compose安装Redis - 更新完毕

    0.前言 有我联系方式的那些半吊子的人私信问我:安装Redis有没有更简单的方式,网上那些文章和视频,没找到满意的方法,所以我搞篇博客出来说明一下我的安装方式吧 1.准备工作 保证自己的linux中已 ...

  4. A Child's History of England.50

    'Knave [man without honor]!' said King Richard. 'What have I done to thee [you] that thou [you] shou ...

  5. Angular @Input讲解及用法

    1.什么是@input @input的作用是定义模块输入,是用来让父级组件向子组件传递内容. 2.@input用法 首先在子组件中将需要传递给父组件的变量用@input()修饰 需要在子组件ts文件i ...

  6. 在 windows 系统上 安装与配置 PHP + Apache

    参考:http://www.cnblogs.com/pharen/archive/2012/02/06/2340628.html 在大学时候上过一门PHP课时,因为课堂需要配置过一次PHP+Mysql ...

  7. set、multiset深度探索

    set/multiset的底层是rb_tree,因此它有自动排序特性.set中的元素不允许重复必须独一无二,key与value值相同,multiset中的元素允许重复. set的模板参数key即为关键 ...

  8. RAC中常见的高级用法-组合

    组合: concat组合:           按一定顺序执行皇上与皇太子关系 concat底层实现:     1.当拼接信号被订阅,就会调用拼接信号的didSubscribe     2.didSu ...

  9. Mysql 分页查询sql优化

    先查下数据表的总条数: SELECT COUNT(id) FROM ts_translation_send_address 执行分页界SQL 查看使用时间2.210s SELECT * FROM ts ...

  10. C语言static关键字

    C语言static关键字 static关键字的作用,主要从在程序的生存周期.作用域和在代码段中的位置起作用. 全局变量 静态全局变量 局部变量 静态局部量 生存周期 程序运行到结束 程序运行到结束 函 ...