首頁 後端開發 php教程 最大子序列跟算法分析

最大子序列跟算法分析

Jun 13, 2016 pm 12:23 PM
gt int lt return

最大子序列和算法分析

问题描述:给定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(n3),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 a[100];
cin >> 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;
}

这个算法比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 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_BorderLeft=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); /*返回治的结果*/
}
int Max(int a, int b, int c){    /*找出3者中最大的数*/
if ( a>= b&&a >= c)
return a;
if (b >= a&&b >= c)
return b;
if (c >= b&&c>=a)
return c;
}

我们来算一算这个算法时间复杂度:

T(1)=1;

T(n)=2T(n/2)+O(n);

=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];
cin >> n;
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;
}

这种算法是将读入的数据一个个扫描一遍,只有一个for循环,解决同一个问题算法差别大,在于一个窍门,让计算机记住一些关键的中间结果,避免重复计算。

 

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

華為GT3 Pro和GT4的差異是什麼? 華為GT3 Pro和GT4的差異是什麼? Dec 29, 2023 pm 02:27 PM

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

C語言return的用法詳解 C語言return的用法詳解 Oct 07, 2023 am 10:58 AM

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

PHP中int型別轉換為位元組的方法詳解 PHP中int型別轉換為位元組的方法詳解 Mar 06, 2024 pm 06:18 PM

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

修復:截圖工具在 Windows 11 中不起作用 修復:截圖工具在 Windows 11 中不起作用 Aug 24, 2023 am 09:48 AM

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

Java中return和finally語句的執行順序是怎樣的? Java中return和finally語句的執行順序是怎樣的? Apr 25, 2023 pm 07:55 PM

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

C++程式將double類型的變數轉換為int型別 C++程式將double類型的變數轉換為int型別 Aug 25, 2023 pm 08:25 PM

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

int32的取值範圍是多少 int32的取值範圍是多少 Aug 11, 2023 pm 02:53 PM

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

go語言怎麼將int轉為字串型 go語言怎麼將int轉為字串型 Jun 04, 2021 pm 03:56 PM

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

See all articles