演算法1:暴力列舉所有連續子列和,算其中最大的。複雜度$o(n^3)$。
演算法2:為演算法1的優化,去掉內層求連續和的迴圈,在之前遍歷陣列,預處理出字首和,方便在\(o(1)\)內算出連續子列和。複雜度\(o(n^2)\)。
演算法3:分治法,當前處理區間的連續和等於左邊最大連續和與右邊連續和與跨區間中點連續和的最大值。遞迴基為區間長度為一的情況,最大連續和就是本身。複雜度\(o(nlogn)\)。
演算法4:動態規劃演算法,\(dp[n]\)表示以第n個元素結尾的最大子列和,
轉移方程為:\(dp[n]=num[n]+max(0,dp[n-1])\),意思是如果\(dp[n-1]\)大於零,則以第n個元素結尾的區間和就接上前面的子列和,如果小於零,就另立門戶,說明前面的和不可能是全域性最大的了.複雜度\(o(n)\)。
演算法5:思想:sum陣列表示字首和,\(sum[n]-sum[m-1]\)就是從m到n的子列和。要\(sum[n]\)最大,就要找\(sum[m-1]\)最小。在遍歷過程中計算字首和,更新最小字首和與子列和的最大值。
演算法6:思想:遍歷陣列,不斷計算累加和並更新最大子列和,一旦和小於零,另立門戶,繼續計算。(注:只適用於有正有負數列,全為負則返回零)
如更詳細,參見參考文章。
統一說明:數列數字從下標\(1\)開始,個別方法會對原陣列修改,若不想這樣使用時可以稍作修改,比如另設累計變數,但應注意遍歷範圍有無改變
#include using namespace std;
int n = 6;
int maxsum_1()//暴力列舉
; int ans = num[1];
for(int i = 1;i<=n;i++)//以i為起點j為終點的子列的和
if(sum>ans)}}
return ans;
}int maxsum_2()//暴力法字首和優化
; int sum[1000];//儲存字首和
sum[0] = 0;
int ans = num[1];
for(int i = 1;i<=n;i++)
for(int i = 1;i<=n;i++)
}sum = 0;
int rmax = num[mid+1];
for(int i = mid+1;i<=r;i++)
}int ans = lmax+rmax;
ans = max(ans,lans);
ans = max(ans,rans);//在上述三種情況下取最大值
return ans;
}int maxsum_4()//num[i]表示以第i個數結尾的連續子列的最大和
; int ans = num[1];
num[0]=0;
for(int i = 1;i<=n;i++)
}return ans;
}int maxsum_5()
; int lmin = 0;
num[0] = 0;
int ans = num[1];
for(int i = 1;i<=n;i++)
if(lmin>num[i])//更新最小字首和
}return ans;
}int maxsum_5_1()
}}int maxsum_6(int num)//當全為負數時返回的是零,即數列必須有正有負
ans = max(ans,tmp);
}}int main()
求最大子列和的四種演算法
問題描述 有乙個陣列有正有負,問起最大的連續子列的和是多少。求最大子列和 a1,a2,a3.an 方法1,暴力搜尋 int maxsubseqsum1 int a,int n return max int maxsubseqsum2 int a,int n return max 分治法 int ma...
經典演算法 求最大子列和
題目 最大連續子數列和一道很經典的演算法問題,給定乙個數列,其中可能有正數也可能有負數,我們的任務是找出其中連續的乙個子數列 不允許空序列 使它們的和盡可能大。我們一起用多種方式,逐步優化解決這個問題。為了更清晰的理解問題,首先我們先看一組資料 8 2 6 1 5 4 7 2 3 輸出 14 題解 ...
求最大子列和
給定乙個含有n整數的序列,求其最大子列和 即該序列中一段連續子串行和的最大值 大致思路是 定義乙個當前位置之前的序列和的最大值 maxsum 以及當前子串行的和 thissum 每迭代一次比較二者的大小關係,如果maxsum小於thissum,則更新maxsum,否則繼續遍歷。當thissum 0時...