416. 分割等和子集 0/1背包问题

416. 分割等和子集

难度:中等
就是很经典的0/1背包问题,背包容量有限,对于每个物品要么全选要么不选,而且每个位置只能选一次,看最后能不能装满背包
题目描述
在这里插入图片描述

解题思路

1、二维dp

dp[i][j]表示前i个物品能不能组合成等于j的
先计算target,就是整个数组和的一半,然后开始装背包
初始化第一列,就是不管多少个物品都能组成容量为0的背包
状态转移方程:dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]];
对于每个位置要么选要么不选,不选就是dp[i-1][j],选就是dp[i-1][j-nums[i-1]]
这两种情况任何一种是true,那这个位置就是true

/*
					  * 416. 分割等和子集
					  * 2020/9/8
					  * medium
					  */
					 public boolean canPartition(int[] nums) {
						 
						 int sum = 0;
						 for (int i = 0; i < nums.length; i++) {
							sum += nums[i];
						}
						 //如果数组总和是奇数,肯定不能分成两个
						 if(sum%2 != 0) {
							 return false;
						 }
						 int target = sum/2,n = nums.length;
						//转换成0/1背包问题,能不能从这个n个数字里找到总和刚好等于target的组合
						 //dp[i][j]表示前i个物品能不能组合成等于j的
						 boolean[][] dp = new boolean[n+1][target+1];  
						 for (int i = 0; i <= n; i++) {
							dp[i][0] = true;
						}

						 for (int i = 1; i <= n; i++) {
							 for (int j = nums[i-1]; j <= target; j++) {
								dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]];
								 
							}
						}
						 
						 return dp[n][target];
						 
					    }

在这里插入图片描述

一维dp

状态转移方程:dp[j] = dp[j] || dp[j-nums[i]];
要么等于本身,不选,要么选,与上一个状态相同

public boolean canPartition1(int[] nums) {
						 
						 int sum = 0;
						 for (int i = 0; i < nums.length; i++) {
							sum += nums[i];
						}
						 //如果数组总和是奇数,肯定不能分成两个
						 if(sum%2 != 0) {
							 return false;
						 }
						 int target = sum/2,n = nums.length;
						//转换成0/1背包问题,能不能从这个n个数字里找到总和刚好等于target的组合
						 //dp[i][j]表示前i个物品能不能组合成等于j的
						 boolean[] dp = new boolean[target+1];  
						 dp[0] = true;
						 for (int i = 0; i < n; i++) {
							for (int j = target; j >= nums[i]; j--) {
								dp[j] = dp[j] || dp[j-nums[i]];
							}
						}
						 
						 
						 return dp[target];
						 
					    }

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值