专栏名称: 九章算法
专业的北美IT求职经验分享、技术交流社区,帮助你找到好的IT工作。由硅谷顶尖IT企业工程师维护。提供专业的算法培训/面试咨询,官网 www.jiuzhang.com
目录
相关文章推荐
九章算法  ·  谷歌高管寒冬!裁员10%! ·  5 天前  
九章算法  ·  实习无return,亚麻mgr手段太low! ·  4 天前  
九章算法  ·  上班暂停!!0元送超级VIP年卡! ·  5 天前  
九章算法  ·  2025年LeetCode刷题小分队正式开始 ... ·  4 天前  
算法爱好者  ·  三个顶尖程序员,居然过得这么惨! ·  4 天前  
51好读  ›  专栏  ›  九章算法

Ebay 面试题 | 把数组分成和大小一样的集合

九章算法  · 公众号  · 算法  · 2017-01-04 02:35

正文


题目描述


给定一个只包含正整数的非空数组,判断该数组能否分成两个和相等的子数组。


样例输入

输入[1,5,11,5] 返回 true . 可以分为[1,5,5]和[11]
输入[1,2,3,5]    返回false. 无法分为相等的两个子数组


算法分析

本题需要判断数组能否分为两个和想等的子数组,等价于在数组中选取一定数目的元素,能否使得选择的元素之和为sum/2(sum为数组中所有元素的和)。而等价的问题就是经典的0-1背包问题,即给定一个正整数数组,能否从数组中选取一定数量的元素,使得这些元素的和恰好为sum/2。


     为了解决这个问题,直观的想法是我们可以枚举原数组的所有子集,计算每个子集的元素之和能否等于sum/2,但是含有n个元素的数组的子集数目为2^n个,这样算法的复杂度是指数级别的,在n比较大的时候并不可行。


     我们假设数组中存在子集num1,num2,...,numk满足和为sum/2,那么,从该子集中去掉最后一个元素numk,其和一定为sum/2-numk。也就是说子问题:是否存在一个子集,其和为sum/2-numk,该问题一定是有解的(可以用反证法证明)。


      这样,我们可以确定,原问题有解当且仅当子问题有解。这样,我们就把一个规模比较大的问题归结成了规模比较小的子问题。这就是动态规划的思想。那么,我们如何确定子问题是否有解呢?可以这样考虑,假设dp[i][j]表示数组中前i个元素能否得到和为j的子数组,dp[i][j] = 1表示前i个元素能够得到和为j的子数组,dp[i][j] = 0 表示不能得到。那么对于第i个元素来说,有两种情况,一种是第i个元素在和为j的子数组中,那么对于前i-1个元素来讲,应该得到和为j-nums[i]的子数组;另一种情况是第i个元素不在和为j的子数组中,那么对于前i-1个元素来讲,应该得到和为j的子数组。上述两种情况成立其一就可以保证能够得到合法解。因此我们有以下关系:


  dp[i][j] = dp[i-1][j] | dp[i-1]][j-nums[i]]


上述解法的时间复杂度和空间复杂度均为O(n*sum)的,由于问题中,n*sum = 200 * 100  * 200 = 4*10^6,我们x需要优化空间复杂度。进一步思考我们发现,第i次迭代的过程只与第i-1次迭代过程有关系,而与前i-2次迭代过程无关。因此我我们首先可以考虑使用2×sum的滚动数组来解决此题。此时可以把空间复杂度压缩到O(sum)。


另一种解法是一维动态规划,我们假设dp[j]表示第i轮迭代能否得到和为j的子数组,那么只要保证此时数组中存储的是上一轮(i-1轮)迭代的结果,我们就可以去掉一个维度。因此我们有如下关系: 


dp[j] = dp[j] | dp[j - nums[i]]


但是这种情况下,内层循环必须从大往小循环(请读者思考为什么)。
下面给出O(sum)空间复杂度的一维动态规划解法。


参考代码




面试官角度分析


本题是动态规划的经典问题0-1背包的简单变形,给出动态规划算法可以达到hire的程度。


LintCode相关练习题

http://www.lintcode.com/zh-cn/problem/backpack-i/
http://www.lintcode.com/zh-cn/problem/backpack-ii/
http://www.lintcode.com/zh-cn/problem/backpack-iii/
http://www.lintcode.com/zh-cn/problem/backpack-vi/
http://www.lintcode.com/zh-cn/problem/backpack-v/


想进FLAG实习?九章帮你系统讲解面试算法,解决面试时常见算法问题


以下课程,正在报名中!

《九章算法班》

《算法强化班》

《Java入门与基础算法班》

《Big Data 项目实战班》

第一节免费试听!!

报名网址http://t.cn/RAC7Era, 或猛戳“阅读原文”