码迷,mamicode.com
首页 > 编程语言 > 详细

算法导论笔记2 - T(n) = O(n) 的最大子数组问题解法

时间:2015-05-17 09:14:16      阅读:107      评论:0      收藏:0      [点我收藏+]

标签:

import random

__author__ = Administrator

LENGTH = 500
base = []

for i in range(0, LENGTH * 2):
    base.append(random.randint(-1 * LENGTH, LENGTH))

print(base)
bsa_i = 0
bsa_j = 1
bsa = base[0]
bord = base[0]
bord_i = 0

for i in range(1, len(base)):
    if bord < 0:
        bord_i = i
        bord = base[i]
    else:
        bord += base[i]
    if bord >= bsa:
        bsa_i = bord_i
        bsa_j = i + 1
        bsa = bord
print(bsa_i, bsa_j, bsa)
print(base[bsa_i: bsa_j])

# verify:
bsa = -1 * LENGTH - 1
for i in range(0, len(base)):
    for j in range(i + 1, len(base) + 1):
        it = 0
        for k in range(i, j):
            it += base[k]
        if it > bsa:
            bsa = it
            bsa_i = i
            bsa_j = j
print(bsa_i, bsa_j, bsa)
print(base[bsa_i: bsa_j])

指针 i 右移时,记录以 i + 1 为右边界的最大子数组 bord,初始为 bord[0, 1],当 sum bord < 0 时, bord 左边界替换为 i 。 这种求法意为去掉左边的所有和为负的子数组,剩下的便是以 i + 1 为右边界的最大子数组。正确性可以这样验证:

 

反证法

原命题: bord[i, j] 中,如果不存在 k 属于 [i, j] 使得 sum A[i, k] <= 0, 这时不存在 l 属于 [i, j] 使得 sum B[l, j] >= sum bord[i, j]。

假设:bord[i, j] 中,如果不存在 k 属于 [i, j] 使得 sum A[i, k] <= 0, 这时存在 l 属于 [i, j] 使得 sum B[l, j] >= sum bord[i, j]。

如果 存在 l 属于 [i, j] 使得 sum B[l, j] >= sum bord[i, j],那么 sum C[i, l] = sum bord[i, j] - sum B[l, j] <= 0

令 l = k, 则假设矛盾不成立,原命题正确性得证。

 

bsa 数组记录的是 [0, i] 中的最大子数组,而 border 是 右边界为 i + 1 的最大子数组,若 sum border > sum bsa,则 border 成为 bsa。这样在一次遍历中,就完成了对整个数组的最大子数组 bsa 的查找,时间复杂度为 O(n),之后的验证算法采用三重循环暴力求解,时间复杂度为O(n ^ 3)。而三次方级别的复杂度对于一个稍大的 n 来讲,几乎就是一个无用的算法,所以设计高效的子数组求法是具有很强的实际意义的。

算法导论笔记2 - T(n) = O(n) 的最大子数组问题解法

标签:

原文地址:http://www.cnblogs.com/zbdzzg/p/4509100.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!