作者: 负雪明烛
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. Scrapy爬虫框架的安装和使用

    Scrapy是一个十分强大的爬虫框架,依赖的库比较多,至少需要依赖的库有Twisted 14.0.lxml 3.4和pyOpenSSL 0.14.在不同的平台环境下,它所依赖的库也各不相同,所以在安装 ...

  2. 大数据学习day22------spark05------1. 学科最受欢迎老师解法补充 2. 自定义排序 3. spark任务执行过程 4. SparkTask的分类 5. Task的序列化 6. Task的多线程问题

    1. 学科最受欢迎老师解法补充 day21中该案例的解法四还有一个问题,就是当各个老师受欢迎度是一样的时候,其排序规则就处理不了,以下是对其优化的解法 实现方式五 FavoriteTeacher5 p ...

  3. 【原创】Altium生成Gerber时跳出The Film is too small for this PCB的解决办法

    在用altium Designer画板子的时候,要生成gerber文件的时候,会出错,出现这样的提示框:"The Film is too small for this PCB" 原 ...

  4. pyqt5的下拉菜单,可以进行输入文字

  5. ping (网络诊断工具)

    Ping是Windows.Unix和Lnix系统下的一个命令,ping也属于一个通信协议,是TCP/IP协议的一部分,利用Ping命令可以检查网络是否连通,可以很好地帮助我们分析和判定网络故障.应用格 ...

  6. 【Linux】【Services】【DNS】使用Bind搭建DNS服务

    1. 简介 1.1. 实现的功能:DNS解析以及智能转发 1.2. 官方文档: 1.3. 基础概念:http://www.cnblogs.com/demonzk/p/6494968.html 2. 环 ...

  7. 莫烦python教程学习笔记——validation_curve用于调参

    # View more python learning tutorial on my Youtube and Youku channel!!! # Youtube video tutorial: ht ...

  8. 【JavaWeb】【JSP】【Bean】JavaBean基础使用方法与操作步骤

    JavaBean基础使用方法与操作步骤 JavaWeb jsp Bean 项目结构 JavaBean的概念 JavaBean是可复用的.平台独立的软件组件 JavaBean既可以是简单的GUI要素,如 ...

  9. Java如何生成随机数 - Random、ThreadLocalRandom、SecureRandom

    Java7 的Random伪随机数和线程安全的ThreadLocalRandom 一.Random伪随机数: Random 类专门用于生成一个伪随机数,它有两个构造器: 一个构造器使用默认的种子(以当 ...

  10. Redis学习推荐资料合集

    目录 一.官方 二.书籍 三.推荐博客 一.官方 redis官网 redis中文网 redis中文命令网 redis模块 redis-github源码 redis报告 二.书籍 <Redis开发 ...