求解最大子数组
来源:互联网 发布:ubuntu清空文件夹 编辑:程序博客网 时间:2024/06/11 23:59
求解最大子数组
问题描述,神马是最大子数组
假定我们一个已知的数组为:
int numbers[]={1,2,6,3,-5,-7,1,-6,8};
现在我们需要求解其中某几个数之和最大的一段子数组,如果不考虑方法的复杂性,首先我们可以考虑暴力求解,即将所有可能的组合进行排列组合。那么我们可以得到n*(n-1)/2(不考虑顺序的排列组合)种可能,其复杂度为O(n^2)。
为求得更好的解题思路,我们可以考虑使用分治法。
首先我们将数组按照中点分成两个部分
这样求解最大子数组的问题就变成了求左边部分,右边部分,跨过中间部分的最大子数组,其中求解左边和右边与求解整个数组的最大子数组逻辑相同。关键在于如何求解中间部分的最大子数组。对于求解中间部分的最大子数组,由于该数组会经过中点,所以可以分解为两部分,分别为从middle向左出发,到左边某个index的最大值以及从middle出发,到右边某个index的最大值。将两个部分的最大值相加即可得到跨过中点的最大子数组,其时间复杂度为O(n);其基本实现如下:
public static Model findCrossMiddle(int leftIndex,int middle,int rightIndex){ int leftSum=Integer.MIN_VALUE; int leftRes=middle; int rightSum=Integer.MIN_VALUE; int rightRes=middle+1; int sum=0; for(int i=middle;i>=leftIndex;i--){ sum+=numbers[i]; if(sum>leftSum){ leftSum=sum; leftRes=i; } } //从middle向左出发,到左边某个index的最大值,并记录下标 sum=0; for(int j=middle+1;j<=rightIndex;j++){ sum+=numbers[j]; if(sum>rightSum){ rightSum=sum; rightRes=j; } } //从middle向左出发,到左边某个index的最大值,并记录下标 return new Model(leftRes,rightRes,(leftSum+rightSum));}
实现算法
分析完基本实现思路,很自然就想到通过递归完成算法,要想通过递归,就要先知道算法的结束条件。在这里就是当划分的子数组只有一个元素时,则直接返回。在每次递归的时候,比较左中右三段中的哪个最大子数组最大,并返回表示该段中的最大子数组。
其完整实现代码如下:
public class MaxChildArray { private static int numbers[]={1,2,6,3,1,8}; public static void main(String[] args) { Model res=findMaxChildArray(0,numbers.length-1); System.out.println(res); } //查找最大子数组的递归方法 public static Model findMaxChildArray(int leftIndex,int rightIndex){ if(leftIndex==rightIndex){ return new Model(leftIndex,rightIndex,numbers[leftIndex]); } else{ int middle=((leftIndex+rightIndex)/2); Model modelLeft=findMaxChildArray(leftIndex,middle); Model modelRight=findMaxChildArray(middle+1, rightIndex); Model acrossModel=findCrossMiddle(leftIndex,middle,rightIndex); if(modelLeft.getSum()>=modelRight.getSum()&&modelLeft.getSum()>=acrossModel.getSum()){ return modelLeft; } else if(modelRight.getSum()>=modelLeft.getSum()&&modelRight.getSum()>=acrossModel.getSum()){ return modelRight; } else{ return acrossModel; } } } //查找经过中点的最大子数组 public static Model findCrossMiddle(int leftIndex,int middle,int rightIndex){ int leftSum=Integer.MIN_VALUE; int leftRes=middle; int rightSum=Integer.MIN_VALUE; int rightRes=middle+1; int sum=0; for(int i=middle;i>=leftIndex;i--){ sum+=numbers[i]; if(sum>leftSum){ leftSum=sum; leftRes=i; } } sum=0; for(int j=middle+1;j<=rightIndex;j++){ sum+=numbers[j]; if(sum>rightSum){ rightSum=sum; rightRes=j; } } return new Model(leftRes,rightRes,(leftSum+rightSum)); } //定义数据模型 public static class Model{ private int leftIndex; private int rightIndex; private int sum; public Model(int leftIndex, int rightIndex, int sum) { super(); this.leftIndex = leftIndex; this.rightIndex = rightIndex; this.sum = sum; } public int getLeftIndex() { return leftIndex; } public void setLeftIndex(int leftIndex) { this.leftIndex = leftIndex; } public int getRightIndex() { return rightIndex; } public void setRightIndex(int rightIndex) { this.rightIndex = rightIndex; } public int getSum() { return sum; } public void setSum(int sum) { this.sum = sum; } @Override public String toString() { return "Model [leftIndex=" + leftIndex + ", rightIndex=" + rightIndex + ", sum=" + sum + "]"; } } }
0 0
- 求解最大子数组
- 求解最大子数组
- 求解最大子数组问题
- 求解最大子数组问题
- 子数组最大和 动态规划求解
- Python实现求解最大子数组问题
- 分治法求解最大子数组问题
- 分治策略求解最大子数组问题
- 分治法求解最大子数组问题
- 求解最大连续子数组的算法
- 搜索算法-求解最大子数组
- JavaScript趣题:求解最大子数组之和
- 求解最大连续子数组问题
- 分治策略求解子数组最大和并输出下标
- 求解最大子数组问题的三种方法
- 【算法学习】最大子数组问题的分治法求解
- 最大子数组求解问题(算法导论)
- 最大子数组问题的分治求解算法
- $(window).width()与window.innerWidth的区别
- 初步了解java中的import和package
- Spark快速开始
- There is a cycle in the hierarchy
- CryptoJS中AES256(CBC)加密算法简单使用
- 求解最大子数组
- 欢迎使用CSDN-markdown编辑器
- HDU 1284 钱币兑换问题 完全背包
- vb.net 教程 3-2 窗体编程之窗体 1
- POJ 1465 Multiple(BFS+同余剪枝)
- 洛谷 P2045 方格取数加强版 (费用流)
- tld xml cvc-complex-type.2.4.a: Invalid content was found starting with element
- 一行代码解决各种IE兼容问题,IE6,IE7,IE8,IE9,IE10
- Mina Iobuffer中常用方法与介绍