image.png

思路

回溯会超时,必须动态规划。
此时 数组长度为物品数量,数组大小为物品重量与价值,目标是
当背包大小为 sum/2时,背包的价值总量正好也是sum/2

一维dp

  1. var canPartition = function(nums) {
  2. const sum =nums.reduce((x,y)=>x +y)
  3. if(sum%2 !=0) return false //无法平分
  4. let dp =new Array(sum/2 +1).fill(0)
  5. // 物品个数
  6. for(let i=0;i<nums.length;i++){
  7. for(let j=sum/2;j>=nums[i];j--){
  8. //背包重量递减
  9. dp[j] =Math.max(dp[j],(dp[j-nums[i]]+nums[i]))
  10. if(dp[j]===sum/2) return true
  11. }
  12. }
  13. return dp[sum/2]===sum/2
  14. };

二维dp

  1. var canPartition = function(nums) {
  2. const sum =nums.reduce((x,y)=>x +y)
  3. if(sum%2 !=0) return false //无法平分
  4. let dp =new Array(nums.length+1).fill(0).map(()=> new Array(sum/2 +1).fill(0))
  5. // 第一个数只填充大于等于它的那个背包格子
  6. for(let i=nums[0];i<sum/2;i++){
  7. if(i<=sum/2){
  8. dp[0][i] =nums[0]
  9. }
  10. }
  11. // 物品个数
  12. for(let i=1;i<=nums.length;i++){
  13. for(let j=0;j<=sum/2;j++){
  14. if(j>=nums[i]){
  15. dp[i][j] =Math.max(dp[i-1][j],dp[i-1][j-nums[i]]+nums[i])
  16. }else{
  17. dp[i][j] =dp[i-1][j]
  18. }
  19. }
  20. }
  21. return dp[nums.length][sum/2]===sum/2
  22. };