力扣:494目标和:动态规划详细(一步步分解代码)步骤解答!

    科技2024-04-18  10

    力扣:494目标和:动态规划详细(一步步分解代码)步骤解答!

    解题思路第一步第二部第三步代码

    解题思路

    首先思路:dp[i][j],i代表现在有多少数相加了,j代表相加数的总和,所以我们只要得到i = nums.length-1的时候,也就是所有数都用到加减的时候,后面这个j相等,且dp[nums.length][sum]的值就是相加最终得到的方法数。

    第一步

    先创建一个二维数组,行为2001,因为题目说的初始数组的和不会超过1000,所以我们把总和都加上1000防止数组索引有负数,正数加上1000最大就是2000了。所以数组的大小取的2001。

    第二部

    初始化:先把原nums数组的第一个值与dp数组对应,dp[0][nums[0] + 1000] = 1; dp[0][-nums[0] + 1000] += 1; 第一个值置为1,第二个值置为+=的原因是因为怕nums[0]等于0,这样这两个值本身就相等了,那么这个值就应该直接为2,因为出现了两次加减不一样,但值一模一样的。

    第三步

    第一个for循环,i为有i个数相加,之后第二个for循环,直接找所有sum的可能性,后面的if判断代表,只要是存在的可能就会大于0,之后if里面的两个语句,分别就是多加上一个数的值,因为dp[0][x],x(x!=1000)应该有两个值,那么dp[1][x],x应该就有四个值,依此类推,但是只要碰到有相同的值,就会叠加到一起,因为后面用的都是+=,之后答案就出来了,就是要算dp[nums.length - 1][S + 1000]的值!

    代码

    public class Solution { public int findTargetSumWays(int[] nums, int S) { int[][] dp = new int[nums.length][2001]; dp[0][nums[0] + 1000] = 1; dp[0][-nums[0] + 1000] += 1; for (int i = 1; i < nums.length; i++) { for (int sum = -1000; sum <= 1000; sum++) { if (dp[i - 1][sum + 1000] > 0) { dp[i][sum + nums[i] + 1000] += dp[i - 1][sum + 1000]; dp[i][sum - nums[i] + 1000] += dp[i - 1][sum + 1000]; } } } return S > 1000 ? 0 : dp[nums.length - 1][S + 1000]; } }

    Processed: 0.027, SQL: 12