welcome to my blog

LeetCode Top 100 Liked Questions 416. Partition Equal Subset Sum (Java版; Medium)

题目描述

Given a non-empty array containing only positive integers, find if the array can be partitioned into two
subsets such that the sum of elements in both subsets is equal.Note:Each of the array element will not exceed 100.
The array size will not exceed 200.Example 1:Input: [1, 5, 11, 5]Output: trueExplanation: The array can be partitioned as [1, 5, 5] and [11].Example 2:Input: [1, 2, 3, 5]Output: falseExplanation: The array cannot be partitioned into equal sum subsets.

01背包: 行是物品, 列是容量

class Solution {public boolean canPartition(int[] nums) {int sum = 0;for(int a : nums){sum += a;}if((sum&1)==1){return false;}sum = sum/2;//01背包//创建二维状态数组,行:物品索引,列:容量(包括 0)//dp[i][j]表示nums[0,i]中每个元素最多使用一次, 是否可以拼凑出目标金额j//dp[i][j]表示nums[0,i]以nums[i]结尾时, 是否可以拼凑出目标金额j   选或者不选nums[i], 这样就能限制每个元素最多使用一次//dp[i][j] = dp[i-1][j]  不选nums[i]//dp[i][j] = dp[i-1][j-nums[i]]  选nums[i]boolean[][] dp = new boolean[nums.length][sum+1];//初始化第一行if(nums[0]<=sum){dp[0][nums[0]] = true;}//初始化第一列for(int i=0; i<nums.length; i++){dp[i][0] = true;}for(int i=1; i<nums.length; i++){for(int j=1; j<sum+1; j++){dp[i][j] = dp[i-1][j];if(j-nums[i]>=0){dp[i][j] = dp[i][j] || dp[i-1][j-nums[i]];}}}return dp[nums.length-1][sum];}
}

第一次做; 背包问题; 优化二维DP的空间复杂度, 优化成一维; 核心:普通的二维dp中, dp[i][j]只依赖它正上方的元素,和正上方左边的某个元素; 优化后仍是两层for循环, 第二层for循环要从后往前遍历, 因为前面的状态不会依赖后面的状态, 所以改变后面的状态没有影响, 但是绝对不能从前往后遍历; 先把普通的dp掌握牢固

/*
优化dp的空间复杂度
*/
class Solution {public boolean canPartition(int[] nums) {int sum = 0;for(int a: nums)sum += a;//sum必须是偶数,否则返回falseif(sum%2==1)return false;//int target = sum>>1;boolean[] dp = new boolean[target+1];//初始化dp[0]=true;for(int j=1; j<=target; j++){if(nums[0]==j) //dp[j] = nums[0]==jdp[j]=true;}//dp主体for(int i=1; i<nums.length; i++){//核心:从后往前遍历for(int j=target; j>=1; j--){//不选nums[i]; 不用执行操作////选nums[i]if(j>=nums[i])dp[j] = dp[j] || dp[j-nums[i]];}}return dp[target];}
}

坚持画图

第一次做; 背包问题; 为什么这道题没法直接从暴利递归转成dp? 为什么这道题没法通过memo[]数组优化暴利递归?

  • 时间复杂度O(N^2)
  • 空间复杂度O(N)
/*
dp[i][j]:表示从数组的 [0, i] 这个区间内挑选一些正整数,每个数只能用一次,能否使这些数的和等于 j。dp[i][j] means whether the specific sum j can be gotten from the first i numbers上面上个解释不同, 个人倾向第一种解释, 但是第二种解释也很清晰为什么?
这道题没法直接从暴利递归转成dp
这道题没法通过memo[]数组优化暴利递归
*/
import java.util.Arrays;class Solution {public boolean canPartition(int[] nums) {int sum = 0;for(int a:nums)sum += a;//sum必须是偶数; 因为数组内的元素都是整数, 两个相同的整数相加一定是偶数if(sum%2==1)return false;int target = sum>>1;int n = nums.length;boolean[][] dp = new boolean[n][target+1];//初始化for(boolean[] d : dp)Arrays.fill(d, false);dp[0][0] = true;//第0列for(int i=0; i<n; i++)dp[i][0] = true;//第0行for(int j=1; j<=target; j++){if(nums[0] == j)dp[0][j]=true;}//dp主体for(int i=1; i<n; i++){for(int j=1; j<=target; j++){//不选nums[i]dp[i][j] = dp[i-1][j];//选nums[i]if(j>=nums[i])dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i]];}}//return dp[n-1][target];}
}

第一次做; 对于每个位置:选或者不选; 递归终止条件:1)index==nums.length; 2)currSum*2==sum;递归函数逻辑:选或者不选当前元素,然后新条件新递归; 超时:28 / 105

/*
我的第一反应: 尝试各种可能, 针对每个位置的操作:选或不选
题解说这是背包问题, 那么什么是背包问题?
*/
class Solution {public boolean canPartition(int[] nums) {//ensure a non-empty arr//int sum = 0;for(int i=0; i<nums.length; i++){sum += nums[i];}return core(nums, 0, 0, sum);       }public boolean core(int[] nums, int index, int currSum, int sum){//base caseif(index==nums.length)return false;if(currSum<<1 == sum)return true;//对于当前位置index, 选或者不选boolean res = false;//不选res = core(nums, index+1, currSum, sum);if(res==true)return true;//选res = core(nums, index+1, currSum+nums[index], sum);return res;}
}

LeetCode最优解

This problem is essentially let us to find whether there are several numbers in a set which are able to sum to a specific
value (in this problem, the value is sum/2).Actually, this is a 0/1 knapsack problem, for each number, we can pick it or not. Let us assume dp[i][j] means whether the
specific sum j can begotten from the first i numbers. If we can pick such a series of numbers from 0-i whose sum is j,
dp[i][j] is true, otherwise it is false.Base case: dp[0][0] is true; (zero number consists of sum 0 is true)Transition function: For each number, if we don't pick it, dp[i][j] = dp[i-1][j], which means if the first i-1 elements
has made it to j, dp[i][j] would also make it to j (we can just ignore nums[i]). If we pick nums[i]. dp[i][j] = dp[i-1][j-nums[i]],
which represents that j is composed of the current value nums[i] and the remaining composed of other previous numbers.
Thus, the transition function is dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i]]talking is cheap:
public boolean canPartition(int[] nums) {int sum = 0;for (int num : nums) {sum += num;}if ((sum & 1) == 1) {return false;}sum /= 2;int n = nums.length;boolean[][] dp = new boolean[n+1][sum+1];for (int i = 0; i < dp.length; i++) {Arrays.fill(dp[i], false);}dp[0][0] = true;for (int i = 1; i < n+1; i++) {dp[i][0] = true;}for (int j = 1; j < sum+1; j++) {dp[0][j] = false;}for (int i = 1; i < n+1; i++) {for (int j = 1; j < sum+1; j++) {dp[i][j] = dp[i-1][j];if (j >= nums[i-1]) {dp[i][j] = (dp[i][j] || dp[i-1][j-nums[i-1]]);}}}return dp[n][sum];
}
But can we optimize it? It seems that we cannot optimize it in time. But we can optimize in space. We currently use two dimensional array to solve it, but we can only use one dimensional array.So the code becomes:
public boolean canPartition(int[] nums) {int sum = 0;for (int num : nums) {sum += num;}if ((sum & 1) == 1) {return false;}sum /= 2;int n = nums.length;boolean[] dp = new boolean[sum+1];Arrays.fill(dp, false);dp[0] = true;for (int num : nums) {for (int i = sum; i > 0; i--) {if (i >= num) {dp[i] = dp[i] || dp[i-num];}}}return dp[sum];
}

LeetCode Top 100 Liked Questions 416. Partition Equal Subset Sum (Java版; Medium)相关推荐

  1. leetcode 416. Partition Equal Subset Sum | 416. 分割等和子集(Java)

    题目 https://leetcode.com/problems/partition-equal-subset-sum/ 题解 乍一看是背包问题,但不同的是,本题要求结果等于某值,背包要求结果小于某值 ...

  2. 【leetcode】416. Partition Equal Subset Sum

    题目如下: 解题思路:对于这种判断是否的题目,首先看看动态规划能不能解决.本题可以看成是从nums中任选i个元素,判断其和是否为sum(nums)/2,很显然从nums中任选i个元素的和的取值范围是[ ...

  3. LeetCode Top 100 Liked Questions 221. Maximal Square (Java版; Medium)

    welcome to my blog LeetCode Top 100 Liked Questions 221. Maximal Square (Java版; Medium) 题目描述 Given a ...

  4. LeetCode Partition Equal Subset Sum(动态规划)

    问题:给出一个数组,问是否可以分成两个子集,其和相等 思路:首先要求数组和是偶数,然后用动态规划来求. 用dp(i,j)表示第i步时和为j是否可行,则有dp(i,j)= dp(i-1,j) || dp ...

  5. leetcode416. Partition Equal Subset Sum

    题目要求 Given a non-empty array containing only positive integers, find if the array can be partitioned ...

  6. LeetCode Top 100 Liked 点赞最高的 100 道算法题

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:刷题顺序,刷题路径,好题,top100,怎么刷题,Leet ...

  7. LeetCode面试常见100题( TOP 100 Liked Questions)

    这篇文章是关于LeetCode Top 100 Liked Questions 的 专栏记录,其中部分题目可能包括解题思路和多种优化解法.我把自己的思路都记录在这里,如果你看见了,请记得点个赞吧,蟹蟹 ...

  8. leetcode 530. 二叉搜索树的最小绝对差(Java版)

    题目 https://leetcode-cn.com/problems/minimum-absolute-difference-in-bst/ 题解 中序遍历法. 本题要求二叉搜索树任意两节点差的绝对 ...

  9. leetcode 235. 二叉搜索树的最近公共祖先(Java版,树形dp套路)

    题目 原题地址:leetcode 235. 二叉搜索树的最近公共祖先 说明: 所有节点的值都是唯一的. p.q 为不同节点且均存在于给定的二叉搜索树中. 题解 关于 树形dp 套路,可以参考我的另一篇 ...

  10. 【leetcode刷题】70.最少操作使数组递增——Java版

    ⭐欢迎订阅<leetcode>专栏,每日一题,每天进步⭐ 如果不限制对某个数进行+1 而是运行+1 或者-1 .那么本题怎么该如何解呢? --leetcode此题热评 前言 哈喽,大家好, ...

最新文章

  1. mysql 给表起别名_MySQL ------ 高级联结 (自联结,自然联结,外联结,带聚合函数的联结)(十五)...
  2. 百兆以太网传输距离_罗森伯格陪你做车载——汽车以太网(三)
  3. PIM-SM DR指定路由器以及 PIM-DM指定前转器的区别 【转自网络】
  4. Presto日志中出现大量的Triggering GC to avoid Code Cache eviction bugs
  5. C# 温故而知新:Stream篇(七)
  6. 2012-04-12
  7. jsp 体检信息查询 绕过用户名验证_一篇彻底搞懂jsp
  8. 文档丨Oracle 20c 概念手册
  9. 前台发送 ajax 请求到后台传递数组参数
  10. 后序非递归遍历二叉树的应用
  11. 转:Ajax调用Webservice和后台方法
  12. 感觉最近有多个机器人给吾博客评论
  13. Ubuntu18.04安装WPS
  14. win10家庭版升级到专业版
  15. 小米路由器r2d_小米路由器R2D亮黄灯维修
  16. 怎么更改计算机网上邻居,如何更换登入网上邻居帐号
  17. win7配置powershell环境变量
  18. Linux重新挂载磁盘,如何把磁盘挂载到已有目录上面
  19. idou老师教你学Istio 16:如何用 Istio 实现微服务间的访问控制
  20. B1031. 查验身份证

热门文章

  1. 冰冻三尺非一日之寒-自学篇 浅谈个人学习方法
  2. 如何使用MATLAB coder将MATLAB代码转换成C/C++语言(详细图文教程)
  3. 【100+ python基础入门-26】python修改列表元素方法
  4. 基于共振解调的轴承故障诊断方法总结(一)
  5. debconf: DbDriver “config“: /var/cache/debconf/config.dat is locked by another process的解决方法
  6. python游戏开发实战:黑客帝国特效
  7. vue 移动端弹窗后禁止页面滚动 @touchmove.prevent
  8. OutMan——Foundation框架中的常用结构体、NSNumber类和NSValue类
  9. js、css基础总结
  10. 基于Ip的刷投票排名及刷百度推广的自动化实现