博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
494. Target Sum
阅读量:4258 次
发布时间:2019-05-26

本文共 2739 字,大约阅读时间需要 9 分钟。

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:
The length of the given array is positive and will not exceed 20.
The sum of elements in the given array will not exceed 1000.
Your output answer is guaranteed to be fitted in a 32-bit integer.

该题是一道meduim的题,但是刚看到题意,立马有了回溯遍历的,但是细想,不可能会这么简单吧,但还是写了一下回溯的代码如下:

void dfs_Target(vector
& nums, int target, int pos, int subsum,int &count){ if (pos == nums.size()){ if (subsum == target)count++; return; } dfs_Target(nums, target, pos + 1, subsum + nums[pos], count); dfs_Target(nums, target, pos + 1, subsum - nums[pos], count);}int findTargetSumWays(vector
& nums, int S) { if (nums.size() == 0)return 0; int count = 0; dfs_Target(nums, S, 0, 0, count); return count;}

私以为这样的时间复杂度很高,测试一下虽然过了,但是只超过16.7%的算法

细想有没有其他的算法能够解决此问题,冥思苦想一会不得其解,故上网上了看了一下别人的代码,果然有妙计,还要什么电视机。。。

int findTargetSumWays(vector
& nums, int S) { if (nums.size() == 0)return 0; unordered_map
dp; dp[0] = 1; for (auto num : nums){ unordered_map
temp; for (auto x : dp){ int sum = x.first, count = x.second; temp[sum + num] += count; temp[sum - num] += count; } dp = temp; } return dp[S];}

这样用了两个map,第一个map一直保持键值和键值和所对应的出现的次数,第二个map一直在循环中作为中间变量;

【问题分析】

1、该问题求解数组中数字只和等于目标值的方案个数,每个数字的符号可以为正或负(减整数等于加负数)。

2、该问题和矩阵链乘很相似,是典型的动态规划问题

3、举例说明: nums = {1,2,3,4,5}, target=3, 一种可行的方案是+1-2+3-4+5 = 3

该方案中数组元素可以分为两组,一组是数字符号为正(P={1,3,5}),另一组数字符号为负(N={2,4}) 因此:    sum(1,3,5) - sum(2,4) = target          sum(1,3,5) - sum(2,4) + sum(1,3,5) + sum(2,4) = target + sum(1,3,5) + sum(2,4)          2sum(1,3,5) = target + sum(1,3,5) + sum(2,4)          2sum(P) = target + sum(nums)          sum(P) = (target + sum(nums)) / 2 由于target和sum(nums)是固定值,因此原始问题转化为求解nums中子集的和等于sum(P)的方案个数问题

4、求解nums中子集合只和为sum(P)的方案个数(nums中所有元素都是非负)

int subsetSum(vector
& nums, int s){ vector
dp(s + 1, 0); dp[0] = 1; for (auto num : nums){ for (int i = s; i >= num; i--){ dp[i] += dp[i - num]; } } return dp[s];}int findTargetSumWays(vector
& nums, int S) { int sum = 0; for (auto x : nums)sum += x; return sum < S || (S + sum) & 1 ? 0 : subsetSum(nums, (S + sum) >> 1);}

转载地址:http://ksxei.baihongyu.com/

你可能感兴趣的文章
抽象类和接口区别
查看>>
JVM学习之对象内存布局,对象头
查看>>
Python urllib模块访问网络
查看>>
JVM学习之java线程安全&锁优化技术
查看>>
兼容ProgressBar圆形设置颜色
查看>>
git detached HEAD 修改后如何提交修改到其他分支
查看>>
Android获取系统中的其他应用信息
查看>>
Android视频编解码之MediaCodec简单入门
查看>>
Android原始视频格式YUV,NV12,NV21,YV12,YU12(I420)
查看>>
View绘制01-Android渲染系统中的View
查看>>
View绘制02-View生命周期
查看>>
View绘制系列(3)-自定义View简介
查看>>
View绘制系列(5)-Canvas基础图形绘制
查看>>
Android横竖屏切换
查看>>
判断SD是否存在及其容量查询
查看>>
linux查看文本的5+1种方式
查看>>
Linux 查看服务器开放的端口号
查看>>
端口状态说明 LISTENING、ESTABLISHED、TIME_WAIT及CLOSE_WAIT
查看>>
阿里云---阿里云服务器ECS开放8080端口
查看>>
Linux如何查看端口状态
查看>>