最大子数组问题及其变形

来源:互联网 发布:iphone录制屏幕软件 编辑:程序博客网 时间:2024/06/11 19:29

最大子数组问题:

############################################ 最大非空子数组 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 allmaxprint maxsubarray(test)print maxsubarray2(test)

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

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


############################################ 二维矩阵的最大子数组 2016.4.4# 类似于积分图像的概念import random,pprint,timeh,w,ran = 100,100,10test = [[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,thejs = 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
原创粉丝点击