题目:
思路
背包问题:有一个容量为 V 的背包,和一些物品。这些物品分别有两个属性,体积 w 和价值 v,每种物品只有一个。要求用这个背包装下价值尽可能多的物品,求该最大价值,背包可以不被装满。
本题是简单的背包问题,只需要考虑将物品分成两个背包,使价值相等,无体积限制。
具体每个步骤看代码注释,写的很清楚~
提交
/**
* @param {number[]} nums
* @return {boolean}
*/
var canPartition = function(nums) {
let length = nums.length
if (length <= 1) {
return false
}
let sum = 0
for (let i = 0; i < length; i++) {
sum += Number(nums[i])
}
if (sum % 2 !== 0) {
return false
}
let dp = [] // dp[i][j]代表前i项能否填满容量为j的背包里,可选择不装入
let maxCap = sum / 2
// 多一列用于存放初始值,i从1开始代表实际物品
for (let i = 0; i <= length; i++) {
dp[i] = []
dp[i][0] = true // 容量为0当然是可以填满的
// 其实还需要初始化dp[0][j](j > 0)第一行为false,但用JS实现,未初始化的值为undefine
}
// 下一步当然是遍历dp[i][j] === 遍历物品,再遍历背包容量
for (let i = 1; i <= length; i++) {
// 注意 当前的物品实际上是nums[i - 1]
for (let j = 1; j <= maxCap; j++) {
if (j < nums[i - 1]) {
// 放不下
dp[i][j] = dp[i - 1][j] || false // 避免undefined的结果
} else {
// 放得下 放还是不放?
// 放 === 未放该物品之前的dp:dp[i - 1][j - nums[i - 1]]
// 不放 === 未放该物品之前的dp:dp[i - 1][j]
// 最终结果只是是否可以填满 用||运算,其中跟上面一样,需要避免undefined || undefined的结果
dp[i][j] = dp[i - 1][j - nums[i - 1]] || dp[i - 1][j] || false
}
}
}
// i = length, j = maxCap
return dp[length][maxCap]
}