标签:code big 行号 || 暴力 str color 复杂度 pack
给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。
返回可以使最终数组和为目标数 S 的所有添加符号的方法数。
来源:力扣(LeetCode)
解法一:暴力(超时)
不贴代码了,求出全部可能性,并遍历,得到目标为S的数量。时间复杂度2的N次方。
解法二:递归
注意,初始的数组的和不会超过1000。这句话及其关键。定义一个数组,列号为nums数组的前几个数。行号为这几个数组合之和,值为这个值的数量。由于组合之和可能为负数,且范围在[-1000,1000],所以一共需要有2001行,第0行代表和为-1000。
递归关系式为
getRes(res,nums.length,S,nums)=getRes(res, length-1, s-nums[length-1],nums)+getRes(res, length-1, s+nums[length-1],nums)。
代码如下(注意要对行号进行判断,有可能溢出):
1 package Leetcode; 2 public class findTargetSumWays { 3 public int findTargetSumWays(int[] nums, int S) { 4 if(S>1000||S<-1000){return 0;} 5 int[][] res = new int[2001][2]; 6 7 res[nums[0]+1000][1]+=1; 8 res[-nums[0]+1000][1]+=1; 9 10 int count = getRes(res,nums.length,S,nums); 11 return count; 12 } 13 14 private int getRes(int[][] res, int length, int s,int[] nums) { 15 if(length==1){ 16 if(s>1000||s<-1000){return 0;} 17 return res[s+1000][1]; 18 } 19 int small = getRes(res, length-1, s-nums[length-1],nums); 20 int big = getRes(res, length-1, s+nums[length-1],nums); 21 return small+big; 22 } 23 }
解法三:dp
其实这道题dp和递归的思想是一样的,只是dp是从前往后推,递归是从后往前推。代码如下
1 class Solution { 2 public int findTargetSumWays(int[] nums, int S) { 3 int[][] dp = new int[nums.length][2001]; 4 dp[0][nums[0] + 1000] = 1; 5 dp[0][-nums[0] + 1000] += 1; 6 for (int i = 1; i < nums.length; i++) { 7 for (int sum = -1000; sum <= 1000; sum++) { 8 if (dp[i - 1][sum + 1000] > 0) { 9 dp[i][sum + nums[i] + 1000] += dp[i - 1][sum + 1000]; 10 dp[i][sum - nums[i] + 1000] += dp[i - 1][sum + 1000]; 11 } 12 } 13 } 14 return S > 1000 ? 0 : dp[nums.length - 1][S + 1000]; 15 } 16 }
标签:code big 行号 || 暴力 str color 复杂度 pack
原文地址:https://www.cnblogs.com/zhangbochao/p/12485240.html