Maximum Subarray | & ||
2016-07-06 11:10
253 查看
Maximum Subarray
Given an array of integers, find a contiguous subarray which has the largest sum.Notice
The subarray should contain at least one number.
Example
Given the array A=
[−2,2,−3,4,−1,2,1,−5,3], the contiguous subarray
[4,−1,2,1]has the largest sum =
6.
分析:
对于A[i]来讲,为了使得subarray最大,那么A[i]前的值必须要大于1,如果小于0,我们需要从A[i]开始重新,那么subarray的新起点就可能是A[i].
public class Solution { /** * @param nums: A list of integers * @return: A integer indicate the sum of max subarray */ public int maxSubArray(int[] nums) { if (nums == null || nums.length == 0) return 0; int tempMax = nums[0]; int max = nums[0]; for (int i = 1; i < nums.length; i++) { if (tempMax > 0) { tempMax += nums[i]; } else { tempMax = nums[i]; } max = Math.max(tempMax, max); } return max; } }
这里介绍另外一种方法,来自于博客:http://blog.csdn.net/linhuanmars/article/details/21314059
这是一道非常经典的动态规划的题目,用到的思路我们在别的动态规划题目中也很常用,以后我们称为”局部最优和全局最优解法“。基本思路是这样的,在每一步,我们维护两个变量,一个是全局最优,就是到当前元素为止最优的解是,一个是局部最优,就是必须包含当前元素的最优的解。接下来说说动态规划的递推式(这是动态规划最重要的步骤,递归式出来了,基本上代码框架也就出来了)。假设我们已知第i步的global[i](全局最优)和local[i](局部最优),那么第i+1步的表达式是:
local[i+1]=Math.max(A[i], local[i]+A[i]),就是局部最优是一定要包含当前元素,所以不然就是上一步的局部最优local[i]+当前元素A[i](因为local[i]一定包含第i个元素,所以不违反条件),但是如果local[i]是负的,那么加上他就不如不需要的,所以不然就是直接用A[i];
global[i+1]=Math(local[i+1],global[i]),有了当前一步的局部最优,那么全局最优就是当前的局部最优或者还是原来的全局最优(所有情况都会被涵盖进来,因为最优的解如果不包含当前元素,那么前面会被维护在全局最优里面,如果包含当前元素,那么就是这个局部最优)。
接下来我们分析一下复杂度,时间上只需要扫描一次数组,所以时间复杂度是O(n)。空间上我们可以看出表达式中只需要用到上一步local[i]和global[i]就可以得到下一步的结果,所以我们在实现中可以用一个变量来迭代这个结果,不需要是一个数组,也就是如程序中实现的那样,所以空间复杂度是两个变量(local和global),即O(2)=O(1)。
代码如下:
public int maxSubArray(int[] A) { if(A==null || A.length==0) return 0; int global = A[0]; int local = A[0]; for(int i=1;i<A.length;i++) { local = Math.max(A[i],local+A[i]); global = Math.max(local,global); } return global; }
Maximum Subarray II
Given an array of integers, find two non-overlapping subarrays which have the largest sum. The number in each subarray should be contiguous. Return the largest sum.Notice
The subarray should contain at least one number.
Example
For given
[1, 3, -1, 2, -1, 2], the two subarrays are
[1, 3]and
[2, -1, 2]or
[1, 3, -1, 2]and
[2], they both have the largest sum
7.
分析:
既然要有两个不重合的subarray,如果左边一个确定了,右边那个一定是在array的右边部分找。对于一个数组,找maximum subarray,不管是从左边找还是从右边找,都是一样的。
public class Solution { /** * @param nums: A list of integers * @return: An integer denotes the sum of max two non-overlapping subarrays * cnblogs.com/beiyeqingteng/ */ public int maxTwoSubArrays(ArrayList<Integer> nums) { if (nums == null || nums.size() == 0) return 0; int[] forwardMax = new int[nums.size()]; forwardMax[0] = nums.get(0); for (int i = 1; i < nums.size(); i++) { if (forwardMax[i - 1] > 0) { forwardMax[i] = nums.get(i) + forwardMax[i - 1]; } else { forwardMax[i] = nums.get(i); } } int[] backwardMax = new int[nums.size()]; backwardMax[backwardMax.length - 1] = nums.get(nums.size() - 1); for (int i = backwardMax.length - 2; i >= 0; i--) { if (backwardMax[i + 1] > 0) { backwardMax[i] = nums.get(i) + backwardMax[i + 1]; } else { backwardMax[i] = nums.get(i); } } int[] rightMax = new int[nums.size()]; rightMax[rightMax.length - 1] = backwardMax[backwardMax.length - 1]; for (int i = rightMax.length - 2; i >= 0; i--) { if (backwardMax[i] >= rightMax[i + 1]) { rightMax[i] = backwardMax[i]; } else { rightMax[i] = rightMax[i + 1]; } } int max = forwardMax[0] + rightMax[1]; for (int i = 1; i < nums.size() - 1; i++) { max = Math.max(max, forwardMax[i] + rightMax[i + 1]); } return max; } }
转载请注明出处:cnblogs.com/beiyeqingteng/
相关文章推荐
- springmvc的下载
- Java中几种代码块的分析
- ejabberd中的http反向推送
- HDU 5096 题解
- 关于SAP中的ICON
- elasticsearch centos7安装
- Xamarin自学教程(Android)之一
- xml解析方式
- php常用header头信息收藏
- 【log4j2 加载配置文件】 加载配置文件的三种方法
- oracle 12c:新特性-限制PGA的大小
- mybatis传参总结
- QT5,5 webview 刷新不出网页解决的办法
- MD5Util (MD5加密摘要算法)。
- swiper的基础使用(十六)
- C++中的宏定义
- Windows 修改MySQL配置文件my.ini不起作用
- 定价类型更新
- 嵌入式 Linux系统编程(五)——目录文件函数
- Fires Dynamics Simulator(FDS)软件运行代码说明