动态规划 LeetCode 背包问题 整理一

01背包:
416.分割等和子集
494.目标和
完全背包:
322.零钱兑换
518.零钱兑换II
377.组合总和IV
139.单词拆分

01背包问题:每个元素只能使用一次。
416.分割等和子集

//使用二维dp数组

class Solution {
    public boolean canPartition(int[] nums) {
        int len = nums.length;
		if(len == 0) {
			return false;
		}
		int sum = 0;
		for(int i = 0; i < len; i++) {
			sum += nums[i];
		}
		
		if((sum&1) == 1) {//根据题意,sum必须是偶数
			return false;
		}
		
		int verge = sum/2;//最大背包的体积
		boolean[][] dp = new boolean[len][verge+1];//前i个物品能放入背包中
		//初始化
		dp[0][0] = true;
		if(nums[0] <= verge) {//至少第一个物体能放入吧
			dp[0][nums[0]] = true;
		}
		
		//开始填表
		for(int i = 1; i < len; i++) {
			for(int j = 0; j <= verge; j++) {
				dp[i][j] = dp[i-1][j];//上一个背包都装不下,换大物件当然也装不下
				if(nums[i] == j) {//正好容量等于背包容量的话
					dp[i][j] = true;
					continue;
				}
				if(nums[i] < j) {//小于背包容量
					//选择放或者不放,如果不放的话,表格的上一个也要为真;如果放的话,j-nums[i]表示能够放下
					dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i]];
				}
			}
		}
		return dp[len-1][verge];//最大容量时能否装满呢
    }
}

//使用一维数组

class Solution {
    public boolean canPartition(int[] nums) {
        int len = nums.length;
		if(len == 0) {
			return false;
		}
		int sum = 0;
		for(int i = 0; i < len; i++) {
			sum += nums[i];
		}
		
		if((sum&1) == 1) {//根据题意,sum必须是偶数
			return false;
		}
		
		int verge = sum/2;//最大背包的体积
		boolean[] dp = new boolean[verge+1];
		dp[0] = true;
		for(int i = 1; i < len; i++) {
			for(int j = verge; nums[i] <= j; j--) {//必须使用倒序,因为dp[j]要由dp[j-nums[i]]推出
				if(dp[verge]) {
					return true;
				}
				dp[j] = dp[j] || dp[j-nums[i]];
			}
		}
		return dp[verge];
    }
}

494.目标和

class Solution {
    public int findTargetSumWays(int[] nums, int S) {
        int len = nums.length;
		 int sum = 0;
		 for (int i : nums) {
			sum += i;
		}
        if(sum < S) return 0;
		 sum = sum + S;
		 if(sum%2 == 1) {
			 return 0;
		 }
         sum = sum/2;
		 int[] dp = new int[sum+1];
		 dp[0] = 1;
		 for(int i = 0; i < len; i++) {
			 for(int j = sum; j >= nums[i]; j--) {
				 if(dp[j-nums[i]] > 0) {
					 dp[j] += dp[j-nums[i]];
				 }
			 }
		 }
		 return dp[sum];
    }
}

完全背包:物品有取0件,取1件,取2件…等多种。
322.零钱兑换

class Solution {
    public int coinChange(int[] coins, int amount) {
		int[] dp = new int[amount+1];//最小硬币数
		Arrays.fill(dp, 1,amount+1, amount+1);
		
		for(int i = 0; i < coins.length; i++) {
			for(int j = coins[i]; j <= amount; j++) {
				if(dp[j-coins[i]] != amount+1) {//如果依然等于amount+1,说明没有硬币可以凑出这个值;
					dp[j] = Math.min(dp[j], dp[j-coins[i]] + 1);
				}
			}
		}
		return dp[amount] == amount+1 ? -1 : dp[amount];
    }
}

518.零钱兑换II

class Solution {
    public int change(int amount, int[] coins) {
        int[] dp = new int[amount+1];
        dp[0] = 1;
		for(int i = 0; i < coins.length; i++) {
			for(int j = coins[i]; j <= amount; j++) {
				if(j >= coins[i]) {
					dp[j] += dp[j-coins[i]];
				}
			}
		}
		return dp[amount];
    }
}

377.组合总和IV

class Solution {
    public int combinationSum4(int[] nums, int target) {
        int[] dp = new int[target+1];
		dp[0] = 1;
		for(int i = 1; i <= target; i++) {
			for(int j = 0; j < nums.length; j++) {
				if(i >= nums[j] && dp[i-nums[j]] > 0) {
					dp[i] += dp[i-nums[j]];
				}
			}
		}
		return dp[target];
    }
}

139.单词拆分

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        int len = s.length();
		 boolean[] dp = new boolean[len+1];
         dp[0] = true;
		 for(int i = 1; i <= len; i++) {
			 for(int j = 0; j < wordDict.size(); j++) {
				 String word = wordDict.get(j);
				 int lenth = word.length();
				 if(i >= lenth && dp[i-lenth]) {
					 String ss = s.substring(i-lenth, i);
					 if(ss.equals(word)) {
						 dp[i] = true;
					 }
				 }
			 }
		 }
		 return dp[len];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值