最大子序列问题

遇到这个问题不会,特地查找了一下相关的方法,在看到的方法中本文的第3个方法的代码思路清晰,相对于分治法虽然复杂度略高,但是有代码更简单更易写的优势

问题描述:
给定整数(可以为负数),A1,A2,A3,…,AN,求子序列最大的值
举例:
对于整数列-1,11,-4,13,-5,-2, 最大的序列值为20 子序列为(11,-4,13)
算法1(楼主首先想到的办法,时间复杂度为:O(n2)):
解析:遍历此序列,取得每个小子序列的值,比较,最后得到最大的序列值,生成以下子序列并取得所有子序列和

-1

-1,11

-1,11,-4,13,-5,-2

11

11,-4

11,-4,13,-5,-2


实现:

public static int maxSubSum2(int [] iargs){ 
int sum=0; 
for(int i=0;i<iargs.length;i++){ 
	int thissum=0; 
	for(int j=i;j<iargs.length;j++){ 
	thissum+=iargs[j]; 
	if(thissum>sum){ sum=thissum; } 
	} 
} 
return sum; 
}

算法2(算是小大招,时间复杂度为O(nlogn)):
解析:在我们例子中,最大的子序列可能存在三个部分,(左边部分、右边部分、左边一部分+右边一部分),如下表所示:

左边部分
右边部分

-1,11,-4
13,-5,-2

左边部分最大子序列为:11,右边部分最大子序列为13,左边+右边最大子序列为20,(11,-4,13)
实现:

public static int maxSubSum3(int[] a,int left,int right){
 int sum=0; 
 if(left==right){ sum=a[left]>0?a[left]:0; return sum; } 
 int center=(left+right)/2; 
 int leftMax=maxSubSum3(a,left,center); 
 int rightMax=maxSubSum3(a,center+1,right); 
 int maxLeftBorder=0,leftBorderSum=0; 
 for(int i=center;i>=left;i--){ 
 	leftBorderSum+=a[i]; 
 	if(maxLeftBorder<leftBorderSum){ 
	 maxLeftBorder=leftBorderSum; 
	 } 
 } 
 int maxRightBorder=0,rightBordeSumr=0; 
 for(int i=center+1;i<=right;i++){ 
 rightBordeSumr+=a[i]; 
 if(maxRightBorder<rightBordeSumr){ 	maxRightBorder=rightBordeSumr; } 
 } 
 return max3(leftMax,rightMax,maxLeftBorder+maxRightBorder); 
 } 
 public static int max3(int a,int b,int c){
  int cen=a>b?a:b; 
  return c>cen?c:cen; 
  }

算法3(大招,时间复杂度为O(n),不看源码想不到,修炼不够啊):
解析:

假设a[i]为负数,则a[i]不可能为此子序列的起始,同理,若a[i]到a[j]的子序列为负,则a[i]到a[j]不可能为子序列的起始,则可以从a[j+1]开始推进,

实现:

public static int maxSubSum4(int a[]){ 
int thisMax=0,maxSum=0; 
for(int i=0;i<a.length;i++){ 
	thisMax+=a[i]; 
	if(thisMax>maxSum){ maxSum=thisMax; } 
	if(thisMax<0){ thisMax=0; } 
} 
return maxSum; 
}

算法三 只对数据进行一次扫描,一旦a[i]被读入并处理,它就不再需要被记忆。因此数组可以被按顺序读入,在主存中不必存储数组的任何部分。具有这种特性的算法叫联机算法(on-line algorithm),仅需要常量空间并以线性时间运行的联机算法几乎是完美算法!

以下为python版实现

# 此算法时间复杂度为O(n2),也是最先想到的算法实现
def maxSubSum1(*a):
    max=0
    for i,value in enumerate(a):
        thisMax=0
        for j in a[i:]:
            thisMax+=j
            if thisMax>max :
                max=thisMax
    return max

#大招,使用递归实现算法,时间复杂度为:O(nlogn)
def maxSubSum2(left,right,*a):
    if left==right:     #base case
        return a[left]

    center =(left+right)/2
    maxLeft=maxSubSum2(left,center,*a)
    maxRight=maxSubSum2(center+1,right,*a)

    leftSum=0
    maxLeftSum=0
    i=center
    while i>=0:
        leftSum+=a[i]
        if leftSum>maxLeftSum:
            maxLeftSum=leftSum
        i=i-1

    rightSum = 0
    maxRightSum = 0
    i = center+1
    while i <=right :
        rightSum += a[i]
        if rightSum > maxRightSum:
            maxRightSum = rightSum
        i = i + 1

    return max(maxLeft,maxRight,maxLeftSum+maxRightSum)

#大大招,时间复杂度为:O(n)
def max(*a):
    max=0
    for i in a:
        if i>max:
            max=i
    return max


def maxSubSum3(*a):
    max=0
    thisMax=0
    for i in a:
        thisMax+=i
        if thisMax>max:
            max=thisMax
        if thisMax<0:
            thisMax=0
    return max

if __name__=='__main__' :
    print maxSubSum1(-1,11,-4,13,-5,-2)
    print maxSubSum2(0,5,-1, 11, -4, 13, -5, -2)
    print maxSubSum3(-1, 11, -4, 13, -5, -2)
原文地址:https://www.cnblogs.com/gao-hongxiang/p/12342435.html