求最大子数组之和及其一些扩展问题

来源:互联网 发布:fabric python 编辑:程序博客网 时间:2024/06/10 03:02

最大子数组之和问题算是非常经典的问题,这里mark一下,以便以后回顾。

先说说二分,设数组为A[start...end],mid = (start + end)>>2,则有3种情况。1.落在start和mid之间,记为left;2.落在mid和end之间,记为right;3.落在中间,则必然包含A[mid],可在O(n)内解决记为middle。所以result=max(left,right,middle),时间复杂度为O(nlgn)

动态规划,以数组的第一个元素为例。A[0]及最大的一段记为A[i]...A[j]。那么有三种情况:

1.i=j=0

2.i=0<j

3.0<i<j

记nAll[0]表示以0开始最大的,那么nAll[0]为上面三种中最大的,用nStart[i]记为以i开始的最大子数组之和。则nAll[0]=max{A[0], A[0]+nStart[1], nAll[1]}。

因为nAll[k+1],nStart[k+1]只被nAll[k]和nStart[k]所用,所以可以用一个元素代替一个数组

代码如下:


import java.util.Random;/** * 求最大的连续子数组之和 * 数据为随机生成的5-15个数 * @author JeremyCai * */public class MaxSum {/** * 动态规划,时间复杂度为O(n) * @param A * @return  * 1.最大值:如果都为负数,则返回最大的负数,如果有0,则返回最后一次出现的0 * 2.开始位置 * 3.结束位置 */public Info maxSum(int[] A){int length = A.length;int nStart = A[length - 1];int nAll = A[length - 1];int start = length - 1, end = length - 1, ostart = length - 1, oend = length - 1;for(int i = length - 2; i >= 0; i--){//nStart = max(A[i], nStart + A[i])if(nStart < 0){nStart = 0;start = i;end = i;}elsestart = i;nStart = nStart + A[i];//nAll = max(nAll, nStart);if(nStart > nAll){nAll = nStart;ostart = start;oend = end;}}return new Info(nAll, ostart, oend);}public static void main(String[] args){MaxSum maxSum = new MaxSum();Random random = new Random();int length = random.nextInt(10) + 5;int[] A = new int[length];for(int i = 0; i < length; i++){A[i] = random.nextInt(15);if(random.nextBoolean())A[i] = -A[i];System.out.print("A["+i+"]="+A[i]+"   ");}Info result = maxSum.maxSum(A);System.out.println("\n"+result);}class Info{int sum;int start;int end;public Info(int sum, int start, int end){this.sum = sum;this.start = start;this.end = end;}public int getSum() {return sum;}public int getStart() {return start;}public int getEnd() {return end;}public String toString(){return "Sum=" + sum + "  start" + start + "  end" + end;}}}

扩展问题:

1.二维的最大子数组之和。

思路是将二维的转化为一维的,对行考虑每种情况,行选取完了后 ,就只剩列的,就变成了一维问题,然后用上面的解法。

2.一维的,手尾连续

有两种情况:

1.结果不跨越手尾,按照上面的解法

2.结果跨越手尾,两种情况

2.1,包含所有数组

2.2,只包含一部分数组,将问题转化为不跨越的,求子数组的和为负数且绝对值最大的



0 0
原创粉丝点击