繼續 算法導論 最大子數組問題,線性時間,這次把索引,也計算出來
思路和代碼,抄襲 https://www.cnblogs.com/jimmy1989/p/8476916.html
感謝作者。
擴展-記錄索引值
這里因為與代碼結合著討論的,所以下標從0開始。
這里再說一下兩個自定義名詞:
前最大子數組:不包含當前元素的最大子數組
邊界最大子數組:只包含當前元素和不只包含當前元素,兩種情況的較大值
我們以數組{1,-2,3,10,-4,7,2,-48}為例。
初始時兩個索引都為0,最大子數組和邊界最大子數組都是1;
當迭代索引為1時,本次值為-2,前一元素的邊界最大子數組為1,所以邊界最大子數組為-1,前最大子數組為1,本次迭代的最大子數組為前最大子數組,值為1,不更新索引;
當迭代索引為2時,本次值為3,前邊界最大子數組為-1,所以邊界最大子數組為3;前最大子數組為1,本次迭代的最大子數組為邊界最大子數組,值為3;此時需要把起始索引和終止索引都更新為當前索引,即2;
當迭代索引為3是,本次值為10,前邊界最大子數組為3,所以邊界最大子數組為13,前最大子數組為3,本次迭代的最大子數組為邊界最大子數組,值為13;此時需要把終止索引更新為當前索引,卻不能更新起始索引;
…………
索引為2和索引為3的共同點在于,都是邊界最大子數組大于前最大子數組,都更新了終止索引;差別在于,索引2為時,邊界最大子數組只包含了索引對應的值,所以可以更新起始索引;而索引3的邊界最大子數組也包含了前一元素,所以只能更新終止索引。
此時可以把需要更新索引的情況概括如下:
條件①:本次的邊界最大子數組只包含當前值,且大于前最大子數組,則更新起始索引;
條件②:本次的邊界最大子數組大于前最大子數組,則更新終止索引;
更新終止索引的條件②應該是充分且必要的,然而更新起始索引的條件①是充分的,確并不是必要的。考慮一下數組{4,-5,1,5},當索引為2時,邊界最大子數組為1,前最大子數組為4,只滿足條件1的前半部分,然而整個數組的最大子數組的起始索引卻是2。所以條件①需要進行補充。
以下是第二個版本的兩個條件:
條件①:本次的邊界最大子數組只包含當前值 ,
(這里說明,如果在后面出現最大子數組,那么,索引從這里開始,
這里把,另一個網站的解釋,復制過來,感謝作者,允許我抄襲,引用
https://blog.csdn.net/songxueyu/article/details/47005557
“在已知A[1...j]的最大子數組的情況下,可以在線性時間內找出形如A[i..j+1]的最大子數組”
這句話里面描述的方法沒有說出來.這里我先把我的結論說出來,接下來再證明。
( 由于原文中的終止索引用l ,小寫的L ,容易看錯,此處用zz 表示)
結論:在已知A[1...j]的最大子數組的情況下(假設A[1..j]的最大子數組是A[k...zz]),找出Ai..j+1的最大子數組是如下三個子數組中的最大和
1.A[k...zz]
2.A[k...j+1]
3.max{A[x...j+1] | x 取值范圍從 zz + 2 至 j + 1}
也就是說,如果新的最大子數組不是原來的最大子數組,那么新的最大子數組的終點必然是j+1.這個是顯而易見的。
假設新的最大子數組不是原來的,那么起點是哪里呢?
1.起點不可能小于k。因為如果小于k,那么說明有A[x...j+1]>A[k...j+1](x<k),即存在A[x...k-1]>0,這顯然是不可能的。
2.起點不可能大于k小于等于zz。因為如果那樣的話,說明有A[x...j+1]>A[k...j+1](k<x<=zz),即A[k...x-1]<0,即最大子數組的起點到它中間某個點小于0,這是不可能的。
3.起點不可能位于zz+ 1,因為A[zz+1]必然小于0。)
條件②:本次的邊界最大子數組大于前最大子數組 (師傅,我又發現一個更大的人參果。)
當滿足條件①時,把當前索引記錄為緩存索引,但并不更新起始索引;
繼續干活,繼續尋找
當滿足條件②時,更新終止索引為當前索引,并且,更新起始索引為緩存索引。
條件②的滿足總是要在條件①之后的。
條件①可能標志著一個新的開始,因為條件①可以重復滿足,每次滿足都應該更新緩存索引。 ,而條件②必定標志著一個結束。
# Hello World program in Python
print "Hello99999 World!\n"
def maxSubArray( array):
length = len(array)
boundry = array[0]
maxArray = array[0]
# copy from https://www.cnblogs.com/jimmy1989/p/8476916.html,thank you
maxEndIndex = 0
maxBeginIndex = 0
tmpBeginIndex = 0
for i in range(1, length):
print '===============================>>>'+str(i)+'>>>go'
if ( boundry > 0 ):
boundry += array[i]
else:
#now boundry <= 0
boundry = array[i]
#we record tmpBeginIndex for use
tmpBeginIndex=i
if( maxArray < boundry ):
maxArray = boundry
maxEndIndex=i
#if boundry == array[i]:
maxBeginIndex=tmpBeginIndex
return [maxArray,maxBeginIndex,maxEndIndex]
#a=[130,-3,-250,120,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7,-99,88,12]
a=[-13,1123,-25,8820,-3,16,-723,18,20,77,-12,-5,22,-15,-4,88,12,-789,999,8,-9,88]
#a=[1,1,1,1,1,1,1,1,-99,2,2,2,2,2,2,2,2,2,2]
print maxSubArray(a)
result
$python main.py
Hello99999 World!
===============================>>>1>>>go
===============================>>>2>>>go
===============================>>>3>>>go
===============================>>>4>>>go
===============================>>>5>>>go
===============================>>>6>>>go
===============================>>>7>>>go
===============================>>>8>>>go
===============================>>>9>>>go
===============================>>>10>>>go
===============================>>>11>>>go
===============================>>>12>>>go
===============================>>>13>>>go
===============================>>>14>>>go
===============================>>>15>>>go
===============================>>>16>>>go
===============================>>>17>>>go
===============================>>>18>>>go
===============================>>>19>>>go
===============================>>>20>>>go
===============================>>>21>>>go
[9931, 1, 5]
木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木 木馬音響積木