LeetCode 494. 目标和

题目描述

给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。

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

示例 1:

输入: nums: [1, 1, 1, 1, 1], S: 3
输出: 5
解释: 

-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

一共有5种方法让最终目标和为3。

注意:

  1. 数组的长度不会超过20,并且数组中的值全为正数。
  2. 初始的数组的和不会超过1000。
  3. 保证返回的最终结果为32位整数。

问题分析

此题用带记忆数组的dfs。创建的记忆数组大小为nums.size(),每个元素都是一个哈希map。dp[i]表示初始位置为 i 时,目标和与相应可能数的映射。开始以初始位置为0,目标和为S的状态调用dfs函数,返回值就是一共的可能数。在dfs函数中,先判断此位置的该目标和是否已经求过,如果之前求过那么直接从哈希map中取出结果返回即可。然后以初始位置为 position+1,目标和为S - nums[position]的状态调用dfs函数 ,返回值记为res1,这是当前position的数取正号时,目标和为S的可能数;然后以初始位置为 position+1,目标和为S + nums[position]的状态调用dfs函数 ,返回值记为res2,这是当前position取负号时,目标和为S的可能数。最后将res1 + res2的值记录在dp[position][S]上,然后返回dp[position][S]。递归基是当position为nums.size()时,如果S等于0,那么返回1,否则返回0。

代码实现

class Solution {
public:
    int findTargetSumWays(vector& nums, int S) {
        vector> dp(nums.size());
        return dfs(0, S, dp, nums);
    }
    
    int dfs(long position, long S, vector>& dp, vector& nums){
        if(position == nums.size()){
            if(S == 0)
                return 1;
            else
                return 0;
        }
        if(dp[position].count(S)) 
            return dp[position][S];
        long res1 = dfs(position + 1, S - nums[position], dp, nums);
        long res2 = dfs(position + 1, S + nums[position], dp, nums);
        dp[position][S] = res1 + res2;
        return dp[position][S];
    }
};

 

你可能感兴趣的:(LeetCode)