一 問題描述:
輸入一組整數,求出這組數字子串行和中最大值。也就是只要求出最大子串行的和,不必求出最大的那個序列。例如:
序列:-3 18 -4 5 -5 -2,則最大子串行和為23。
二 解法1:窮舉解法
1int maxsequence(int a,int
len)
9if(newsum >maxsum)
10 maxsum =newsum;
11} 12}
13return
maxsum;
14 }
這個演算法本身是非常簡單和容易理解的,通過三個for迴圈直接給出所有可能出現的子串行,從中選出乙個最大值即可。但是該方法時間複雜度真的是太大了,達到了o(n3),
有很多操作完成是重複性的操作。例如當i = 0時,j = 1 時:該演算法會計算a[0]+a[1],而當i = 0,j = 2時候,該演算法會計算a[0]+a[1]+a[2],顯然a[0]+a[1]被重複計算了。
三 解法2:窮舉解法2
1int maxsequence2(int a,int
len) 10}
11return
maxsum;
12 }
這個演算法本身其實也是非常容易理解的,它不過是上面那個解法的改進,當我們計算i..j的值時候,i--j-1已經被計算過了,可以直接利用,不用重新計算一次i..j-1。其時間複雜度為o(n2),當然了,很明顯的,這個時間複雜度也還是非常高的,在計算機裡面,乙個演算法複雜度達到o(n2)其實還是一件比較可怕的事情。
四 解法3:分治法
int max3(int i, int j, intk)int max_seq(int a,int left,int
right)
int rmax = a[mid+1
];
int rsum = 0
;for(int i = mid+1;i<=right;i++)
return max3(lmax+rmax,max_seq(a,left,mid),max_seq(a,mid+1
,right));
}int maxsequence3(int a,int
len)
這個演算法的核心就是分治思想。我們假設將我的已經知道的序列分成左右兩部分,那麼最大子串行存在的位置顯然有三種可能:
(1) 存在在序列的左部
(2) 存在在序列的右部
(3) 既存在在序列的左部又存在在序列的右部。
顯然如果是情況(3),是比較容易算出來的。如果是情況(1)和 (2)的話,我們可以將左部和右部當中乙個重新的序列計算,那麼新的序列又可以分成左右部分,重複以上即可。該演算法的時間複雜度了o(n * lg(n))。
五 解法四:動態規劃
int maxsequence4(int a,intlen)
return
maxsum;
}
該演算法的時間複雜度顯然就是o(n),對於計算機來說當然是非常友好的一件事情了,當是對於人來說就不是那麼友好了(當然了,神人除外)。
我們可以想一下,最大的子串行有什麼特點呢?那就是其前m個元素之和也一定不能小於0,為什麼?我們假設
序列a的長度為len,假設a[i].....a[j],表示為a的最大子串行。如果sum[i->i+m]< 0,那麼sum[i+m+1->j] > sum[i->j],矛盾。
**體現:
if(maxnew <= 0)maxnew = a[i];
最大子串行
模板 int maxsubsequence const int a,int n return maxsum 複雜度on 給定k個整數的序列,其任意連續子串行可表示為,其中 1 i j k。最大連續子串行是所有連續子串行中元素和最大的乙個,例如給定序列,其最大連續子串行為,最大和 為20。在今年的資料...
最大子串行
最大子串行是要找出由數組成的一維陣列中和最大的連續子串行。比如的最大子串行就是 它的和是8,達到最大 而 的最大子串行是,它的和是6。你已經看出來了,找最大子串行的方法很簡單,只要前i項的和還沒有小於0那麼子串行就一直向後擴充套件,否則丟棄之前的子串行開始新的子串行,同時我們要記下各個子串行的和,最...
最大子串行
maxsum最大子串行問題。其實是動態規劃問題,遞推式如下 s 1 a 1 s n s n 1 0?s n 1 a n a n 注意點 暴力是可以解決問題,但是時間肯定會超時。暴力就是把所有子串行都查一遍然後找乙個最大的。如序列為123456,它的所有子串行為 1 2 3 4 5 6 12 123 ...