zoukankan      html  css  js  c++  java
  • leetcode 494. Target Sum

    leetcode 494. Target Sum

    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.

    solution

    approach 1 动态规划

    将数组分成两部分,一部分全为正其和为 P,另一部分全为负其和为(-Q)

    P-Q=target
    P+Q+P-Q=target+Q+P
    2P=target+(P+Q)=target+sum(all)
    P=(taget+sum(all))/2
    

    P的值知道了问题就转化为了,从数组中选择若干个数使其和为P,一共有多少种选法?

    令A[n][P]为从第一个到第n个中,选择若干个和为P的选法种数;从而其动态规划的状态转移方程为
    A[n][P]=A[n-1][P]+A[n-1][P-a[n]]
    对于第n个数a[n]来说,如果不选前面的和也为P,那么对于不选a[n],其选法就有A[n-1][p]种,如果选择了a[n]的情况,那么此种选法就有A[n-1][P-a[n]]种选法;
    初始化:当p等于0时,即一个都不选是一种情况,对于第一个数来说,只有P=a[1]时有一种选择的情况
    注意:当一个数字为零是那么可以选择也可以不选择,应该有两种选法

    class Solution {
    public:
    	int findTargetSumWays(vector<int>& nums, int S) {
    
    		int n = nums.size();
    		int sum = 0;
    		for (int i = 0; i < n; i++)
    			sum += nums[i];
    
    		if (S > sum || (sum + S) % 2 != 0)
    			return 0;
    		int cap = (sum + S) / 2;
    
    		int dp[n + 1][sum + 1];
    
    		for (int i = 1; i <= n; i++)
    			for (int j = 0; j <= cap; j++)
    				if (j == 0)
    					if (nums[i - 1] == 0)
    						dp[i][j] = 2;
    					else
    						dp[i][j] = 1;
    				else
    					dp[i][j] = 0;
    		if (nums[0] != 0)
    			dp[1][nums[0]] = 1;
    		else
    			dp[1][nums[0]] = 2;
    		//print("%d",dp[1][1])
    
    		for (int i = 2; i <= n; i++)
    			for (int j = 0; j <= cap; j++)
    			{
    
    				int left = j - nums[i - 1];
    				int tmp = 0;
    				if (left >= 0)
    				{
    					tmp = dp[i - 1][left];
    				}
    				dp[i][j] = dp[i - 1][j] + tmp;
    
    			}
    		return dp[n][cap];
    	}
    };
    

    参考链接

    leetcode

    blogs record our growth
  • 相关阅读:
    js 类型转换学习
    Prototypes in Javascript 收集.__proto__
    不想说作用域scope,因为是scopeTree,
    在家学习 利器 记录每日点滴
    图片切换特效的分析和学习
    js 无缝滚动效果学习
    MySQL 在高并发下的 订单撮合 系统使用 共享锁 与 排他锁 保证数据一致性
    (二)区块链的共识算法:PoS 及其 例子 代码 实现
    以太坊: ETH 发送交易 sendRawTransaction 方法数据的签名 和 验证过程
    Golang 的 协程调度机制 与 GOMAXPROCS 性能调优
  • 原文地址:https://www.cnblogs.com/qwfand/p/12683310.html
Copyright © 2011-2022 走看看