文章目录

  • 题目描述
  • 思路 && 代码
    • 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、动态规划、背包问题、滚动数组)相关推荐

  1. 【Leetcode】416. 分割等和子集

    题目链接:分割等和子集 题目描述:给你一个 只包含正整数 的 非空 数组 nums .请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等. 思路:将数组分割成两个等和的子集. 那么: ...

  2. LeetCode 416. 分割等和子集(动态规划)

    1. 题目 给定一个只包含正整数的非空数组. 是否可以将这个数组分割成两个子集,使得两个子集的元素和相等. 注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200 示例 1: 输入: [ ...

  3. 【Leetcode】416 分割等和子集

    类似0-1背包问题,目的是判断是否存在子数组的和为sum/2. 可以直接返回false的特殊case: 只有1个数 数组和为奇数 最大的数大于数组和的一半 递归数组D[i, j]表示是否A[0:i]是 ...

  4. LeetCode 416. 分割等和子集 【c++/java详细题解】

    来自专栏<LeetCode高频面试题> 欢迎订阅 目录 1.题目 2.思路 3.二维c++代码 4.二维java代码 5.一维优化 6.一维c++代码 7.一维java代码 1.题目 给你 ...

  5. Java实现 LeetCode 416 分割等和子集

    416. 分割等和子集 给定一个只包含正整数的非空数组.是否可以将这个数组分割成两个子集,使得两个子集的元素和相等. 注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200 示例 1: ...

  6. leetcode - 416. 分割等和子集

    416. 分割等和子集 -------------------------------------------- 给定一个只包含正整数的非空数组.是否可以将这个数组分割成两个子集,使得两个子集的元素和 ...

  7. LeetCode 416 分割等和子集

    LeetCode 416 分割等和子集 题目链接 给定一个只包含正整数的非空数组.是否可以将这个数组分割成两个子集,使得两个子集的元素和相等. 注意: 每个数组中的元素不会超过 100 数组的大小不会 ...

  8. 【Leetcode刷题】:Python:416. 分割等和子集

    题目 416. 分割等和子集 代码:dp class Solution:def canPartition(self, nums: List[int]) -> bool:n = len(nums) ...

  9. leetcode 416. 分割等和子集

    分割等和子集题解集合 DFS 记忆化搜索 记忆化搜索的另一种写法 动态规划 「滚动数组」解法 「一维空间优化」解法 DFS 思路 题意就是:给你一个非空数组,和为sum,你能否找到一个子序列,和为su ...

  10. 416. 分割等和子集

    0-1背包问题:https://blog.csdn.net/qq_40794973/article/details/102701052 416. 分割等和子集 https://leetcode-cn. ...

最新文章

  1. 【统计学习】多元统计分析
  2. 固定大小容器内,不同比例的图片高度撑满,宽度居中裁剪
  3. 【PAT】A1079 Total Sales of Supply Chain
  4. 【问链财经-区块链基础知识系列】 第三十八课 以太坊智能合约账户全解析
  5. RichTextBox中表格不能折行的问题
  6. 并发调试和JDK8新特性
  7. 【一】Drupal 入门之新建主题
  8. python bool转string_Python:可以返回boolean和string吗?
  9. requests模块相关用法
  10. java集合框架总结(一)
  11. java的io流的file类_java IO流 (一) File类的使用
  12. Java8 本地DateTime API
  13. 在开发时选择静态方法还是非静态方法
  14. 16. XML DOM
  15. 矢量图片转换 emf to eps
  16. 1526B - I Hate 1111
  17. 红linux系统,红帽子linux系统
  18. 数据包络分析法(DEA)_1
  19. 光功率 博科交换机_交换机是否支持查看光模块型号及收发光功率
  20. 光纤跳线接口_2分钟让你搞懂跳线架和配线架的区别

热门文章

  1. linux nfs命令,linux命令:NFS服务
  2. 网页字段位置php改变,php实现子字符串位置相互对调互换的方法
  3. numpy 转置_Numpy基础:数组转置和轴对换
  4. 如何获取投票提交地址_简单实用 | 2019全国医院擂台赛投票攻略(县域版)
  5. python+OpenCV图像处理(二)图像像素的访问、通道的合并与分离
  6. 数字图像处理 实验一 图像的基本运算
  7. 使用detours实现劫持
  8. C++ 使用 TinyXml 解析 XML 文件
  9. Mockito—参数匹配
  10. CompletableFuture详解~异常处理