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
  • 相关阅读:
    pointcut通配符
    Java设计模式-建造者(Builder)模式
    mybatis 初步使用(IDEA的Maven项目, 超详细)
    静态代理和动态代理
    Java 多线程(五)之 synchronized 的使用
    Java 多线程(四)之守护线程(Daemon)
    HashMap 源码解析(一)之使用、构造以及计算容量
    Java 多线程(三)之线程状态及其验证
    Java 多线程(二)之 Thread 优先级
    Java 多线程之 Thread 类 和 Runnable 接口初步使用
  • 原文地址:https://www.cnblogs.com/qwfand/p/12683310.html
Copyright © 2011-2022 走看看