【leetcode】494 目标和(动态规划,DFS)

题目链接:https://leetcode-cn.com/problems/target-sum/

思路

1 动态规划二维数组

(1)首先求整个数组的和取值范围sum
(2)建立二维数组,数组大小为nums.size() * sum。dp[i][j]表示为到下标i为止和为j的方法数,由于负数等于正数取反,如果j是负数,其方法与j是相反数时相同,即dp[i][-j];
(3)动态规划方程:

dp[i][j] = dp[i-1][abs(j-nums[i])] + dp[i-1][j+nums[i]]

(4)最终返回dp[nums.size()-1][abs(S)]

复杂度分析
时间复杂度:O(mn)
空间复杂度:O(mn)
m为数组长度;n为数组的和

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int S) {
        auto sum = accumulate(nums.begin(), nums.end(), 0); // 和表示范围 [-sum, sum]
        if(nums.empty() ||  S > 1000 || abs(S) > sum)       // 超出表示范围
            return 0;

        vector<vector<int>> dp(nums.size(),vector<int>(sum+1,0));
        //dp[i][j]表示为到下标i为止和为j的方法数,由于负数等于正数取反,如果j是负数,其方法与j是相反数时相同,即dp[i][-j];
        dp[0][nums[0]] = (nums[0] == 0) ? 2 : 1;    // 取第一个数的方法数;nums[0]==0时正负号都可加

        for(int i = 1 ; i < nums.size();++i){
            for(int j = 0 ; j <= sum; ++j){
                int count1 = abs(j-nums[i]) > sum ? 0 : dp[i-1][abs(j-nums[i])];   // +号
                int count2 = ( j + nums[i] ) > sum ? 0 : dp[i-1][j+nums[i]];       // -号
                dp[i][j] = count1 + count2;
            }
        }
        return dp[nums.size()-1][abs(S)];
    }
};

在这里插入图片描述

2 动态规划一维数组

猜你喜欢

转载自blog.csdn.net/zjwreal/article/details/91394765