最大子序列和演算法分析
問題描述:給定n個整數序列{a1,a2,...,an},求函數f(i,j)=max{0,Σak}(k:連續的從i取到j );
問題即為求已連續子列和的最大值,若果最大值為負數則取0,例如8個數序列{-1,2,-3,4,-2,5, -8,3},那摩最大子序列和為4+(-2)+5=7.
這個問題有四種不同複雜度的演算法,演算法1到四的時間複雜度是O(n 3),O(n2),O(nlogn),O(n);
演算法一:
最直接的方法是窮舉法,列出所有的情況,我們可以設定子序列的左端i和右端j,再利用一層計算出a[i]到a[j]的和.
//最大子列和窮舉法
#include
using namespace std;
int Find_Maxsun (int*a, int n);
int main(){
int n, i;
int a[100];
cin >> n;
cout for (i = 0; i cin >> a[i];
cout return 0;
}
int Find_Maxsun(int*a, int n){
int MaxSun = 0, i, j, k;
int NowSum;
for (i = 0; i for (j = 0; j NowSum = 0;
for (k = i; k NowSum += a[k]; /*從a[ i]到a[j]的子序列*/
if (NowSum>MaxSun)
MaxSun = NowSum; /*更新結果*/
}
return MaxSun;
}
很顯然,暴力法使用啦3重for循環,演算法時間複雜度為O(n3),這當然也是一個最笨的演算法,但資料難非常龐大時候,就算是要算到死的節奏,我們可以清楚看到第三層for循環,
j每加一次,子列和都要重頭算一次,那我們為何不去利用j-1的結果呢?也就是說我們將j-1的結果保存下來,在計算j步的結果時候,只需要在j-1步的基礎上再加上a[j],就可以啦,於是有啦算法二。
演算法二:
#include
using namespace std;
int Find_Maxsun2(int*a, int n);
int main(){
int n, i
int;
int main a[1000]; >> n;
cout for (i = 0; i cin >> a[i];
cout return 0;
}
int Find_Maxsun2(int*a, int n){
int i, j, NewSum = 0, MaxSum= 0;
for (i = 0 ; i NewSum = 0;
for (j = i; j NewSum += a [j]; /*每次在j-1條件下更新NewSum*/
if (NewSum>MaxSum) /*更新MaxSum*/
MaxSum = NewSum;
}
}
return MaxSum;
}
} return MaxSum;}
}這個演算法
return MaxSum;比1聰明,演算法複雜度是O(n2
),顯然還不是我們想要的複雜度。 演算法三:演算法三使用的是分治法的思想,基本思想不言而喻先分後治,將問題分解為小問題然後在可以總和小問題來解決,我們把原序列一分為二,則最大子序列在左邊,在右邊,或跨越邊界,基本想法如下:第一步:將原序列一分為二,分成左序列和右序列。 第二步:遞歸求出子序列S左和S右。 第三部:從中分線向兩邊掃描,找出跨越中線的最大子序列和S中。 🎜🎜第四步:求得S=max{S左,S中,S右};🎜🎜程式碼實作如下:🎜#include
using namespace std;
int Find_MaxSum3(int*a,int low,int high);
int Max(int a,int b,int c);
int main(){
int n, i;
int a[100];
cin >> n;
cout for (i = 0; i cin >> a[i];
cout return 0;
}
int Find_MaxSum3(int*a,int low,int high){
int Find_MaxSum3(int*a,int low,int high){
int MaxSum = 0, MidSum, LeftSum, RightSum,i;
MidSum = 0;
if (low == high){ /*遞歸的終止條件*/
if (a[low] > 0)
return a[low] ;
else
return 0;
}
int mid = (low + high) / 2; //找到分的中點
LeftSum = Find_MaxSum3(a, low, mid); /*遞歸找到左邊序列和*/
RightSum = Find_MaxSum3(a, mid + 1, high); /*遞歸找到右邊序列最大子序列和*/
/*然後可以求中間跨越邊界序列的最大和*/
int NewLeft = 0,Max_BLeorder=0 , NewRight = 0,Max_BorderRight=0;
for (i = mid; i >= low; i--){ /*向左掃描找到最大和*/
NewLeft += a[i];
if (NewLeft > Max_BorderLeft)
Max_BorderLeft = NewLeft;
}
for (i = mid + 1; i NewRight+=a[i];
if (NewRight >= Max_BorderRight)
Max_BorderRight = NewRight;
}
MidSum = Max_BorderRight + Max_BorderLeft;
return Max(LeftSum, MidSum, RightSum); /*回傳的結果*//, aint c){ /*找出3者中最大的數*/
if ( a>= b&&a >= c)
return a;
if (b >= a&&b >= c)
return b;
if (c >= a&&b >= c)
return b;
if (c > = b&&c>=a)
return c;
=2kT(n/2k)+kO(n)=2kT(1)+kO(n)(其中n=2k
)=n+ nlogn=O(nlogn);雖然這個演算法已經非常好啦,但是並不是最快的演算法。 演算法四:演算法四叫做線上處理。意思為,每讀入一個資料就進行及時處理,得到的結果是對於目前讀入的資料都成立,即為在任何位置終止讀入,演算法都可以給出正確的解,邊讀邊解。
#include
using namespace std;
int Find_MaxSum4(int*a, int n);
int main(){
int n, i;
int a[100]; cout for (i = 0; i cin >> a[i];
cout return 0;
}
int Find_MaxSum4(int*a, int n){
int i, NewSum = 0, MaxSum = 0;
for (i = 0; i NewSum += a[i]; /*目前子序列和*/
if (MaxSum MaxSum = NewSum; /*更新最大子序列和*/
if (NewSum NewSum = 0;
}
return MaxSum;
}
以上就介紹了最大子序列和演算法分析,包括了方面的內容,希望對PHP教程有興趣的朋友有幫助。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

許多用戶在選擇智慧型手錶的時候都會選擇的華為的品牌,其中華為GT3pro和GT4都是非常熱門的選擇,不少用戶都很好奇華為GT3pro和GT4有什麼區別,下面就給大家介紹一下二者。華為GT3pro和GT4有什麼差別一、外觀GT4:46mm和41mm,材質是玻璃鏡板+不鏽鋼機身+高分纖維後殼。 GT3pro:46.6mm和42.9mm,材質是藍寶石玻璃鏡+鈦金屬機身/陶瓷機身+陶瓷後殼二、健康GT4:採用最新的華為Truseen5.5+演算法,結果會更加的精準。 GT3pro:多了ECG心電圖和血管及安

C語言return的用法有:1、對於傳回值類型為void的函數,可以使用return語句來提前結束函數的執行;2、對於傳回值型別不為void的函數,return語句的作用是將函數的執行結果傳回給呼叫者;3、提前結束函數的執行,在函數內部,我們可以使用return語句來提前結束函數的執行,即使函數並沒有回傳值。

PHP中int類型轉換為位元組的方法詳解在PHP中,我們經常需要將整數類型(int)轉換為位元組(Byte)類型,例如在處理網路資料傳輸、檔案處理或加密演算法等場景中。本文將詳細介紹如何將int類型轉換為位元組類型,以及提供具體的程式碼範例。 1.int型別與位元組的關係在電腦領域,基本資料型別int表示整數,而位元組(Byte)是電腦儲存單位,通常是8位元二進位數據

原始碼:publicclassReturnFinallyDemo{publicstaticvoidmain(String[]args){System.out.println(case1());}publicstaticintcase1(){intx;try{x=1;returnx;}finally{x=3;}}#輸出上述程式碼的輸出可以簡單地得出結論:return在finally之前執行,我們來看下字節碼層面上發生了什麼事情。下面截取case1方法的部分字節碼,並且對照源碼,將每個指令的含義註釋在

為什麼截圖工具在Windows11上不起作用了解問題的根本原因有助於找到正確的解決方案。以下是截圖工具可能無法正常工作的主要原因:對焦助手已開啟:這可以防止截圖工具開啟。應用程式損壞:如果截圖工具在啟動時崩潰,則可能已損壞。過時的圖形驅動程式:不相容的驅動程式可能會幹擾截圖工具。來自其他應用程式的干擾:其他正在運行的應用程式可能與截圖工具衝突。憑證已過期:升級過程中的錯誤可能會導致此issu簡單的解決方案這些適合大多數用戶,不需要任何特殊的技術知識。 1.更新視窗與Microsoft應用程式商店應用程

在C++中,int型別的變數只能保存正整數或負整數值;它們不能保存小數值。有float和double值可用於此目的。為了儲存小數點後最多七位的小數,創建了雙精度資料類型。整數到雙精確度資料類型的轉換可以由編譯器自動完成(稱為「隱式」轉換),也可以由程式設計師向編譯器明確要求(稱為「明確」轉換)。在接下來的部分中,我們將介紹各種轉換方法。隱式轉換編譯器會自動執行隱式類型轉換。要實現這一點,需要兩個變數——一個是浮點類型,另一個是整數類型。當我們簡單地將浮點值或變數分配給整數變數時,編譯器將處理所有其他事情

int32的取值範圍是從-2的31次方到2的31次方減1,即-2147483648到2147483647。 int32是有符號的整數型,表示它可以表示正數、負數和零,它使用1位來表示符號位,而剩餘的31位元用來表示數值。由於一位用來表示符號位,所以int32的有效位數是31位元。

轉換方法:1、使用Itoa()函數,語法「strconv.Itoa(num)」;2、使用FormatInt()函數,可將int型資料轉換成指定進位並以字串的形式傳回,語法「strconv .FormatInt(num,10)」。
