最大子数组问题及其变形

最大子数组问题:

############################################ 最大非空子数组 2016.4.4

##test = [0,-2,3,5,-1,2]
test = [-1,-2,-3,-5,-1,-2]
def maxsubarray(test): # 无法处理全负数的情况
    curmax = 0
    allmax = 0
    for x in test:
        curmax +=x
        if curmax<0:
            curmax = 0
        allmax = max(allmax, curmax)
    return allmax

# 动态规划思路
def maxsubarray2(test): # 可以处理全负数的情况
    nstart = test[-1]
    # 以i开头的最大子数组 nstart[i] = max(test[i], nstart[i+1])
    allmax = test[-1]
    for i in range(len(test)-2,-1,-1):
        nstart = max(test[i], nstart+test[i])
        allmax = max(allmax, nstart)
    return allmax

print maxsubarray(test)
print maxsubarray2(test)

最大子数组问题扩展到2维平面上:

类似于图像处理中常用的积分图像,需要一个O(M*N)的预处理过程。


############################################ 二维矩阵的最大子数组 2016.4.4
# 类似于积分图像的概念
import random,pprint,time
h,w,ran = 100,100,10
test = [[random.randint(-ran,ran) for i in range(w)] for i in range(h)]
##pprint.pprint(test)

def submaxarray2d(test):
    # 计算积分图像
    rows = len(test)
    cols = len(test[0])
    # mat 补边界,方便运算
    mat = [[0]*(cols+1) for i in range(rows+1)]
    # 0行0列需预处理 (时间复杂度m*n)
    for i in range(rows):
        for j in range(cols):
            mat[i+1][j+1] = mat[i+1][j]+mat[i][j+1]-mat[i][j]+test[i][j]

##    def add(a1,a2):
##        return a1+a2
##    mat = reduce(add, mat) # 拉成一维
    
    maxvalue,thei,thej = 0,None,None # (时间复杂度m*n*m*n)
    for i1 in range(rows+1):
        for j1 in range(cols+1): 
            for i2 in range(i1,rows+1):
                for j2 in range(j1,cols+1):
                    cut = mat[i2][j2]-mat[i2][j1]-mat[i1][j2]+mat[i1][j1]
                    if cut>maxvalue:
                        maxvalue = cut
                        thei = (i1, j1)
                        thej = (i2, j2)
            
    return maxvalue,thei,thej

s = time.clock()
print submaxarray2d(test) # 100*100的矩阵耗时7.17203秒
print time.clock()-s


运行结果如下:

由于时间复杂度为O(M*M*N*N),因此当矩阵为100*100时,非常慢




因此还有一种手段,即枚举上下间所有的可能,共N*N种,对每一种使用 MaxSubArray,O(M),共计O(M*N*N)时间复杂度

如下所示:(图片来自编程之美)只需要一维算法嵌入二维算法中即可!



实际过程中,选择较小的维度,进行枚举,使得总复杂度降维 O(M*N*min(M,N))





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值