【LeetCode笔记】416. 分割等和子集(Java、动态规划、背包问题、滚动数组)
文章目录
- 题目描述
- 思路 && 代码
- 1. 动态规划 O(nc) 、O(nc)
- 2. 结合滚动数组 O(nc)、O(c)
- 二刷
打卡第十四天~熬夜也得把题目补上= =
题目描述
- 初看题目,想到的思路是用记忆化DFS来找结果来着。。看了题解才知道是背包问题= =
思路 && 代码
1. 动态规划 O(nc) 、O(nc)
- 参考了liweiwei的这篇题解,里面给背包问题讲了一些相关知识~
- 时空复杂度: n 是 nums 的长度,c 是 sum 的长度。
- dp[i][j]:从[0, i]下标组成的数集里选取元素相加,能否构成 j 。
- 状态转移方程:【[0, i - 1] 可以构成 j】| 【[0, i - 1] 可以构成 j - nums[i]】,满足任一种情况,都可以保证 dp[i][j] == true,因此这里采用 |=
class Solution {public boolean canPartition(int[] nums) {// 题意转化:找到一个集合,满足其和等于 nums 总和的一半 sum / 2int sum = 0;for(int num : nums) {sum += num;}// 奇数,肯定无法满足 sum / 2if(sum % 2 == 1) {return false;}// [0 ~ i 范围的元素][背包容量(包括0)]int target = sum / 2;boolean[][] dp = new boolean[nums.length][target + 1];// 1. 边界:第一个元素,只能满足对应的容量if(nums[0] <= target) {dp[0][nums[0]] = true;}// 2. 状态转移for(int i = 1; i < nums.length; i++) {for(int j = 0; j <= target; j++) {// part 1: 先把上一轮的结果继承下来再说dp[i][j] = dp[i - 1][j];// part 2: 状态转移方程:看[0, i - 1]能不能满足 j - nums[i],再补上 nums[j]if(nums[i] <= j) {dp[i][j] |= dp[i - 1][j - nums[i]];}}}return dp[nums.length - 1][target];}
}
2. 结合滚动数组 O(nc)、O©
- 在1的基础上,通过滚动数组来减少空间复杂度。在剑指Offer 47 礼物的最大值里,也有用到这个方法~。
- 加入 if(dp[target]) 的判断实现剪枝效果,可以打败98%+,这里为了看起来简洁就不加上了
- 注意:逆序是为了达到无后效性的效果。如果正序,会导致后面的列用到的不是上一行的结果,而是当前行的结果,会导致出错(可以画图理解一下,或者看上面1提到的题解的解释)
class Solution {public boolean canPartition(int[] nums) {// 题意转化:找到一个集合,满足其和等于 nums 总和的一半 sum / 2int sum = 0;for(int num : nums) {sum += num;}// 奇数,肯定无法满足 sum / 2if(sum % 2 == 1) {return false;}// [0 ~ i 范围的元素][背包容量(包括0)]int target = sum / 2;boolean[] dp = new boolean[target + 1];// 1. 边界:第一个元素,只能满足对应的容量if(nums[0] <= target) {dp[nums[0]] = true;}// 2. 状态转移for(int i = 1; i < nums.length; i++) {// 逆序,达到无后效性的效果for(int j = target; j >= 0; j--) {// part 1: 先把上一轮的结果继承下来再说(滚动数组不用考虑)// part 2: 状态转移方程:看[0, i - 1]能不能满足 j - nums[i],再补上 nums[j]if(nums[i] <= j) {dp[j] |= dp[j - nums[i]];}}}return dp[target];}
}
二刷
背包!
你就说你选不选吧(指元素)
你要能 true 我肯定选啊
- O(nc)、O(nc)
class Solution {public boolean canPartition(int[] nums) {int sum = 0;for(int num : nums) {sum += num;}if((sum & 1) == 1) {return false;}// dp[i][j]:从 [0, i] 的下标中,能找到和为 j 的值int target = sum / 2;boolean[][] dp = new boolean[nums.length][target + 1];if(nums[0] <= target) {dp[0][nums[0]] = true;}for(int i = 1; i < nums.length; i++) {for(int j = 0; j <= target; j++) {// 继承结果 | 当前可行dp[i][j] = (dp[i - 1][j]) | (nums[i] <= j ? dp[i - 1][j - nums[i]] : false);}}return dp[nums.length - 1][target];}
}
- 滚动数组:逆序降低空间复杂度
class Solution {public boolean canPartition(int[] nums) {int sum = 0;for(int num : nums) {sum += num;}if((sum & 1) == 1) {return false;}int target = sum / 2;boolean[] dp = new boolean[target + 1];if(nums[0] <= target) {dp[nums[0]] = true;}for(int i = 1; i < nums.length; i++) {for(int j = target; j >= 0; j--) {dp[j] |= (nums[i] <= j ? dp[j - nums[i]] : false);}}return dp[target];}
}
【LeetCode笔记】416. 分割等和子集(Java、动态规划、背包问题、滚动数组)相关推荐
- 【Leetcode】416. 分割等和子集
题目链接:分割等和子集 题目描述:给你一个 只包含正整数 的 非空 数组 nums .请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等. 思路:将数组分割成两个等和的子集. 那么: ...
- LeetCode 416. 分割等和子集(动态规划)
1. 题目 给定一个只包含正整数的非空数组. 是否可以将这个数组分割成两个子集,使得两个子集的元素和相等. 注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200 示例 1: 输入: [ ...
- 【Leetcode】416 分割等和子集
类似0-1背包问题,目的是判断是否存在子数组的和为sum/2. 可以直接返回false的特殊case: 只有1个数 数组和为奇数 最大的数大于数组和的一半 递归数组D[i, j]表示是否A[0:i]是 ...
- LeetCode 416. 分割等和子集 【c++/java详细题解】
来自专栏<LeetCode高频面试题> 欢迎订阅 目录 1.题目 2.思路 3.二维c++代码 4.二维java代码 5.一维优化 6.一维c++代码 7.一维java代码 1.题目 给你 ...
- Java实现 LeetCode 416 分割等和子集
416. 分割等和子集 给定一个只包含正整数的非空数组.是否可以将这个数组分割成两个子集,使得两个子集的元素和相等. 注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200 示例 1: ...
- leetcode - 416. 分割等和子集
416. 分割等和子集 -------------------------------------------- 给定一个只包含正整数的非空数组.是否可以将这个数组分割成两个子集,使得两个子集的元素和 ...
- LeetCode 416 分割等和子集
LeetCode 416 分割等和子集 题目链接 给定一个只包含正整数的非空数组.是否可以将这个数组分割成两个子集,使得两个子集的元素和相等. 注意: 每个数组中的元素不会超过 100 数组的大小不会 ...
- 【Leetcode刷题】:Python:416. 分割等和子集
题目 416. 分割等和子集 代码:dp class Solution:def canPartition(self, nums: List[int]) -> bool:n = len(nums) ...
- leetcode 416. 分割等和子集
分割等和子集题解集合 DFS 记忆化搜索 记忆化搜索的另一种写法 动态规划 「滚动数组」解法 「一维空间优化」解法 DFS 思路 题意就是:给你一个非空数组,和为sum,你能否找到一个子序列,和为su ...
- 416. 分割等和子集
0-1背包问题:https://blog.csdn.net/qq_40794973/article/details/102701052 416. 分割等和子集 https://leetcode-cn. ...
最新文章
- 【统计学习】多元统计分析
- 固定大小容器内,不同比例的图片高度撑满,宽度居中裁剪
- 【PAT】A1079 Total Sales of Supply Chain
- 【问链财经-区块链基础知识系列】 第三十八课 以太坊智能合约账户全解析
- RichTextBox中表格不能折行的问题
- 并发调试和JDK8新特性
- 【一】Drupal 入门之新建主题
- python bool转string_Python:可以返回boolean和string吗?
- requests模块相关用法
- java集合框架总结(一)
- java的io流的file类_java IO流 (一) File类的使用
- Java8 本地DateTime API
- 在开发时选择静态方法还是非静态方法
- 16. XML DOM
- 矢量图片转换 emf to eps
- 1526B - I Hate 1111
- 红linux系统,红帽子linux系统
- 数据包络分析法(DEA)_1
- 光功率 博科交换机_交换机是否支持查看光模块型号及收发光功率
- 光纤跳线接口_2分钟让你搞懂跳线架和配线架的区别
热门文章
- linux nfs命令,linux命令:NFS服务
- 网页字段位置php改变,php实现子字符串位置相互对调互换的方法
- numpy 转置_Numpy基础:数组转置和轴对换
- 如何获取投票提交地址_简单实用 | 2019全国医院擂台赛投票攻略(县域版)
- python+OpenCV图像处理(二)图像像素的访问、通道的合并与分离
- 数字图像处理 实验一 图像的基本运算
- 使用detours实现劫持
- C++ 使用 TinyXml 解析 XML 文件
- Mockito—参数匹配
- CompletableFuture详解~异常处理