1. 程式人生 > >Kadane演算法詳解及求解最大子數列和問題

Kadane演算法詳解及求解最大子數列和問題

最大子數列和問題

        給出一個數列,現在求其中一個子數列,要求是所有子數列的和的最大值。另外還有其他問法,例如給出一個數組,要求求出連續的元素和的最大值。可以一個例子來解釋:

假設有數列:[-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;
}