Kadane演算法詳解及求解最大子數列和問題
阿新 • • 發佈:2018-11-07
最大子數列和問題
給出一個數列,現在求其中一個子數列,要求是所有子數列的和的最大值。另外還有其他問法,例如給出一個數組,要求求出連續的元素和的最大值。可以一個例子來解釋:
假設有數列:[-1,2,3,-5,6,-2,4],那麼總共有7^2=49種子數列,如果分別求和,其中最大的子數列為:[6,-2,4],其和為8。
暴力求解
最暴力的演算法是列舉,雙重for迴圈,列舉所有的子數列。這樣時間複雜度為O(n^2),相對而言是比較慢的,但是是最簡單的一種方法。
Kadane演算法
首先安利一個youtube的視訊,能翻牆以及能理解youtube自動尬翻的同學看這個是比較好的,講的還可以,比較詳細:
https://www.youtube.com/watch?v=86CQq3pKSUw
最大子數列和問題的最優解就是Kadane演算法,可以在O(n)的時間複雜度內解決問題,其思想實際是動態規劃。首先在定義狀態的時候,我們宣告dp[i]這個狀態是指以i結尾的子數列中,最大和是多少。而因為有一個重要要求:子數列,所以求和的元素必須是連續的,那麼有狀態轉移方程:
dp[i] = max(n[i],dp[i-1]+n[i]);
那麼,如果我們設定一個指標,始終指向構造dp陣列時的最大值,那麼在遍歷一次數列後,指標指向的值也就是最大值了。
C++ 程式碼
#include<iostream> #define MAX 2333 using namespace std; int n[MAX]; int dp[MAX]; int Max(int a,int b){ return a > b ? b : a; } int kadane(){ int ans = n[0]; dp[0] = n[0]; for(int i = 1;i < strlen(n);i++){ dp[i] = Max(n[i],dp[i-1]+n[i]); ans = Max(dp[i],ans); } } int main(){ // 自設例子 system("pause"); return 0; }