目标和

给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意

一个整数,你都可以从 + 或 -中选择一个符号添加在前面。

返回可以使最终数组和为目标数 S 的所有添加符号的方法数。

1、常规思路 

对于数组中的每一个数,它的符号只有两种选择,一种是取正,一种是取负,根据这两种策略,计算结果。

	int ncount = 0;
	public void solve(int idx, int[] nums, int S)
	{
//		if (S < 0) // 这个边界条件不合适,它会影响结果
//			return;
		if (idx == nums.length && S == 0) // 找到了一个解
		{
			ncount++;
			return;
		}
		
		if (idx == nums.length) 
			return;
		
		solve(idx+1, nums, S-nums[idx]); // nums[idx]符号为正
		solve(idx+1, nums, S+nums[idx]); // nums[idx]符号为负
	}
	
    public int findTargetSumWays(int[] nums, int S) 
    {
    	solve(0, nums, S);
    	return ncount;
    }

2、记忆化搜索

	public int solve(int idx, int[] nums, int S, Map<String, Integer> map)
	{
		// 避免数字重复,无法找到截断点
		String encodeString = idx + "->" + S;
		
		if (map.containsKey(encodeString))
			return map.get(encodeString);
		
		if (idx == nums.length)
		{
			return S == 0 ? 1 : 0; // S==0找到一个解
		}
		
		int curNum = nums[idx];
		int positive = solve(idx+1, nums, S-nums[idx], map);
		int negitive = solve(idx+1, nums, S+nums[idx], map);
		map.put(encodeString, positive+negitive);
		return positive + negitive;
	}
	
    public int findTargetSumWays(int[] nums, int S) 
    {
    	HashMap<String, Integer> hashMap = new HashMap<String, Integer>();
    	if (nums == null || nums.length == 0)
    		return 0;
    	return solve(0, nums, S, hashMap);
    }

3、动态规划

    public int findTargetSumWays(int[] nums, int S) 
    {
    	int sum = 0;
    	if (nums == null || nums.length == 0)
    		return 0;
    	
    	// 计算数组中元素之和
    	for (int i = 0; i < nums.length; i++)
    		sum += nums[i];

    	if (S > sum || (sum + S) % 2 == 1)
    		return 0;
    	return solve(nums, (sum+S)/2);
    }
    
    int solve(int[] nums, int S)
	{
    	int[] dp = new int[S+1]; // 状态矩阵
    	dp[0] = 1; 
    	/*
    	 递归式
    	solve(idx+1, nums, S-nums[idx]); // nums[idx]符号为正
		solve(idx+1, nums, S+nums[idx]); // nums[idx]符号为负
		*/
    	for (int i=0; i<nums.length; i++)
    	{
    		for (int j=S; j>=nums[i]; j--)
    		{
    			dp[j] += dp[j-nums[i]];
    		}
    	}
		return dp[S];
	}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值