welcome to my blog
LeetCode Top 100 Liked Questions 494. Target Sum (Java版; Medium)
题目描述
You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols + and -. For each integer,
you should choose one from + and - as its new symbol.
Find out how many ways to assign symbols to make sum of integers equal to target S.
Example 1:
Input: nums is [1, 1, 1, 1, 1], S is 3.
Output: 5
Explanation:
-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
There are 5 ways to assign symbols to make the sum of nums be target 3.
Note:
The length of the given array is positive and will not exceed 20.
The sum of elements in the given array will not exceed 1000.
Your output answer is guaranteed to be fitted in a 32-bit integer.
class Solution {
public int findTargetSumWays(int[] nums
, int S
) {
int sum
= 0;
for(int a
: nums
){
sum
+= a
;
}
if(S
>sum
){
return 0;
}
if((sum
+S
)%2==1){
return 0;
}
int target
= (sum
+ S
) /2;
int[] dp
= new int[target
+1];
dp
[0] = 1;
for(int i
=0; i
<nums
.length
; i
++){
for(int j
=target
; j
>=nums
[i
]; j
--){
dp
[j
] += dp
[j
-nums
[i
]];
}
}
return dp
[target
];
}
}
class Solution {
public int findTargetSumWays(int[] nums
, int S
) {
int sum
= 0;
for (int a
: nums
) {
sum
+= a
;
}
if(S
>sum
){
return 0;
}
if ((sum
+ S
) % 2 == 1) {
return 0;
}
int target
= (sum
+ S
) / 2;
int[][] dp
= new int[nums
.length
+1][target
+ 1];
dp
[0][0] = 1;
for (int i
= 1; i
< nums
.length
+1; i
++) {
for (int j
= 0; j
< target
+ 1; j
++) {
dp
[i
][j
] = dp
[i
- 1][j
];
if (j
- nums
[i
-1] >= 0) {
dp
[i
][j
] += dp
[i
- 1][j
- nums
[i
-1]];
}
}
}
return dp
[nums
.length
][target
];
}
}
坚持画图
第一次做;背包问题; dp[i][j]表示:前i个数组合成j的可能数量; 以后就用这种含义了! 初始化方便!!! 核心:索引和真实值的对应关系:索引值==真实值+max
class Solution {
public int findTargetSumWays(int[] nums
, int S
) {
int sum
= 0;
for(int a
: nums
){
sum
+= a
;
}
if(S
>sum
){
return 0;
}
if((sum
+S
)%2==1){
return 0;
}
int target
= (sum
+ S
) /2;
int[] dp
= new int[target
+1];
dp
[0] = 1;
for(int i
=0; i
<nums
.length
; i
++){
for(int j
=target
; j
>=nums
[i
]; j
--){
dp
[j
] += dp
[j
-nums
[i
]];
}
}
return dp
[target
];
}
}
class Solution {
public int findTargetSumWays(int[] nums
, int S
) {
int sum
= 0;
for (int a
: nums
) {
sum
+= a
;
}
if(S
>sum
){
return 0;
}
if ((sum
+ S
) % 2 == 1) {
return 0;
}
int target
= (sum
+ S
) / 2;
int[][] dp
= new int[nums
.length
][target
+ 1];
dp
[0][0] = nums
[0]==0?2:1;
if (nums
[0] <= target
) {
dp
[0][nums
[0]] = nums
[0]==0?2:1;
}
for (int i
= 1; i
< nums
.length
; i
++) {
for (int j
= 0; j
< target
+ 1; j
++) {
dp
[i
][j
] = dp
[i
- 1][j
];
if (j
- nums
[i
] >= 0) {
dp
[i
][j
] += dp
[i
- 1][j
- nums
[i
]];
}
}
}
return dp
[nums
.length
- 1][target
];
}
}
第一次做; 转换成背包问题; dp[i][j]的含义:[0,i]的数组合成j的可能数量, 初始化太细节! 不好! ;最容易错的地方有三个: 1)索引和真实值的对应 2)初始化 3)0的存在
class Solution {
public int findTargetSumWays(int[] nums
, int S
) {
if(nums
==null
|| nums
.length
==0)
return 0;
int n
= nums
.length
;
int min
=0,max
=0;
for(int a
:nums
){
max
+= a
;
min
+= -a
;
}
if(S
>max
|| S
<min
)
return 0;
int[][] dp
= new int[n
][max
-min
+1];
for(int j
=0; j
<max
-min
+1; j
++){
if(nums
[0]==0 && j
-max
==0)
dp
[0][j
]=2;
else if(nums
[0]==j
-max
)
dp
[0][j
]=1;
else if(-nums
[0]==j
-max
)
dp
[0][j
]=1;
}
for(int i
=1; i
<n
; i
++){
for(int j
=0; j
<max
-min
+1; j
++){
if(j
-nums
[i
]>=0){
dp
[i
][j
] += dp
[i
-1][j
-nums
[i
]];
}
if(j
+nums
[i
]<max
-min
+1){
dp
[i
][j
] += dp
[i
-1][j
+nums
[i
]];
}
}
}
return dp
[n
-1][S
-min
];
}
}
第一次做; 暴利递归, 竟然通过了全部案例…
class Solution {
public int findTargetSumWays(int[] nums
, int S
) {
if(nums
==null
|| nums
.length
==0)
return 0;
return core(nums
, 0, S
);
}
public int core(int[] nums
, int index
, int sum
){
if(index
==nums
.length
)
return sum
==0? 1: 0;
int notchoseRes
= core(nums
, index
+1, sum
-nums
[index
]);
int choseRes
= core(nums
, index
+1, sum
+nums
[index
]);
return choseRes
+ notchoseRes
;
}
}
LeetCode优秀题解; 我跟他的思路很像,但是为什么他的初始化这么简单?
public int findTargetSumWays2(int[] nums
, int S
) {
if (nums
.length
== 0) {
return 0;
}
int sum
= 0;
for (int num
: nums
) {
sum
+= num
;
}
if (S
< -sum
|| S
> sum
) {
return 0;
}
int[][] dp
= new int[nums
.length
+ 1][sum
* 2 + 1];
dp
[0][sum
] = 1;
int leftBound
= 0;
int rightBound
= sum
* 2;
for (int i
= 1; i
<= nums
.length
; i
++) {
for (int j
= leftBound
; j
< rightBound
+ 1; j
++) {
if (j
+ nums
[i
- 1] <= rightBound
) {
dp
[i
][j
] += dp
[i
- 1][j
+ nums
[i
- 1]];
}
if (j
- nums
[i
- 1] >= leftBound
) {
dp
[i
][j
] += dp
[i
- 1][j
- nums
[i
- 1]];
}
}
}
return dp
[nums
.length
][sum
+ S
];
}