Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
docs: 为 0494.目标和.md 完善 JavaDoc 注释, 添加动规五部曲注释, 规范部分代码格式, 修改部分变量名以增强代码语义化
  • Loading branch information
asnsuyu committed Jan 24, 2025
commit 27718a4dfca99b25ceda3ee2946130c29261be71
61 changes: 50 additions & 11 deletions problems/0494.目标和.md
Original file line number Diff line number Diff line change
Expand Up @@ -825,30 +825,69 @@ func abs(x int) int {

### JavaScript
```javascript
/**
* 题目来源: {@link https://leetcode.cn/problems/target-sum/}
*
* 题解来源: {@link https://programmercarl.com/0494.%E7%9B%AE%E6%A0%87%E5%92%8C.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE}
*
* 时间复杂度: O(n * C), C 为数组元素总和与目标值之和的一半
*
* 空间复杂度: O(C)
*
* @param { number[] } nums
* @param { number } target
* @return { number }
*/
const findTargetSumWays = (nums, target) => {

const sum = nums.reduce((a, b) => a+b);
// 原题目可转化为:
//
// 将所有元素划分为 2 个集合,
// 一个集合中包含所有要添加 "+" 号的元素, 一个集合中包含所有要添加 "-" 号的元素
//
// 设两个集合的元素和分别为 positive 和 negative, 所有元素总和为 sum, 那么有如下等式:
// positive + negative = sum (1)
// positive - negative = target (2)
// (1) 与 (2) 联立可得: positive = (sum + target) / 2,
// 所以如果能从原数组中取出若干个元素形成 1 个元素总和为 (sum + target) / 2 的集合,
// 就算得到了 1 种满足题意的组合方法
//
// 因此, 所求变为: 有多少种取法, 可使得容量为 (sum + target) / 2 的背包被装满?

const sum = nums.reduce((a, b) => a + b);

if(Math.abs(target) > sum) {
if (Math.abs(target) > sum) {
return 0;
}

if((target + sum) % 2) {
if ((target + sum) % 2) {
return 0;
}

const halfSum = (target + sum) / 2;

let dp = new Array(halfSum+1).fill(0);
const bagWeight = (target + sum) / 2;

// 1. dp 数组的含义
// dp[j]: 装满容量为 j 的背包, 有 dp[j] 种方法
let dp = new Array(bagWeight + 1).fill(0);

// 2. 递推公式
// dp[j] = Σ(dp[j - nums[j]]), (j ∈ [0, j] 且 j >= nums[j])
// 因为 dp[j - nums[j]] 表示: 装满容量为 j - nums[j] 背包有 dp[j - nums[j]] 种方法
// 而容量为 j - nums[j] 的背包只需要再将 nums[j] 放入背包就能使得背包容量达到 j
// 因此, 让背包容量达到 j 有 Σ(dp[j - nums[j]]) 种方法

// 3. dp 数组如何初始化
// dp[0] = 1, dp[1 ~ bagWeight] = 0
dp[0] = 1;

for(let i = 0; i < nums.length; i++) {
for(let j = halfSum; j >= nums[i]; j--) {

// 4. 遍历顺序
// 先物品后背包, 物品从前往后遍历, 背包容量从后往前遍历
for (let i = 0; i < nums.length; i++) {
for (let j = bagWeight; j >= nums[i]; j--) {
dp[j] += dp[j - nums[i]];
}
}

return dp[halfSum];
return dp[bagWeight];
};
```

Expand Down