494.目标和
给你一个非负整数数组 nums 和一个整数 target 。
向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :
- 例如,
nums = [2, 1],可以在2之前添加'+',在1之前添加'-',然后串联起来得到表达式"+2-1"。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。
示例 1:
输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 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
+1 + 1 + 1 + 1 - 1 = 3
示例 2:
输入:nums = [1], target = 1
输出:1
提示:
1 <= nums.length <= 200 <= nums[i] <= 10000 <= sum(nums[i]) <= 1000-1000 <= target <= 1000
该题我写了两种方法,一种是回溯法,本题也属于一种选或不选的问题,也能使用回溯法,就是时间复杂度要高得多,另一种是动态规划,时间复杂度则相对较低。
首先是回溯法,只需要递归考虑选或不选,最后判断是否和目标数相同即可。
java
public class hot {
public static void main(String[] args) { // 测试用
int[] nums = {0};
hot hot = new hot();
System.out.println(hot.findTargetSumWays(nums, 0));
}
int res = 0;
public int findTargetSumWays(int[] nums, int target) {
boolean[] isOrNot = new boolean[nums.length];
helper(nums, target,0, 0);
return res;
}
public void helper(int[] nums, int target, int cur, int sum){
if (cur >= nums.length){
if (sum == target){
res++;
}
return;
}
helper(nums, target, cur + 1, sum + nums[cur]);
helper(nums, target, cur + 1, sum - nums[cur]);
}
}
动态规划法比较复杂,要搞清楚动态规划数组的含义才容易理解。dp[i][j]:使用 下标为[0, i]的nums[i]能够凑满j(包括j)这么大容量的包,有dp[i][j]种方法。dp[i][j]处的结果由dp[i - 1][j] 和 dp[i - 1][j - nums[i]]确定,若num[i] <= j时则为两者相加,否则则为dp[i - 1][j]
java
public class hot {
public static void main(String[] args) { // 测试用
int[] nums = {0};
hot hot = new hot();
System.out.println(hot.findTargetSumWays(nums, 0));
}
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
if ((sum + target) % 2 == 1 || Math.abs(target) > sum){
return 0;
}
int size = (sum + target) / 2;
int[][] dp = new int[nums.length][size + 1];
dp[0][0] = 1;
if (nums[0] <= size){
dp[0][nums[0]] = 1;
if (nums[0] == 0){
dp[0][0] = 2;
}
}
for (int i = 1; i < nums.length; i++) {
for (int j = 0; j < size + 1; j++) {
if (nums[i] <= j){
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]];
}else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[nums.length - 1][size];
}
}
以上为记录分享用,代码较差请见谅。