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
  • 相关阅读:
    别人的Linux私房菜(15)磁盘配额与高级文件系统管理
    别人的Linux私房菜(14)Linux账号管理和ACL权限设置
    别人的Linux私房菜(13)学习Shell脚本
    别人的Linux私房菜(12)正则表达式与文件格式化处理
    别人的Linux私房菜(11)认识与学习BASH
    别人的Linux私房菜(10)vim程序编辑器
    别人的Linux私房菜(9)文件与文件系统的压缩
    别人的Linux私房菜(8)Linux磁盘与文件系统管理
    盘点互联网大佬背后的女人,最后一个你肯定认识
    Java工程师学习指南(完结篇)
  • 原文地址:https://www.cnblogs.com/qwfand/p/12683310.html
Copyright © 2011-2022 走看看