時間複雜度 演算法評價的標準

2021-08-28 07:11:02 字數 3206 閱讀 9943

前言:演算法,一直是每個程式設計師的心病,確是程式的核心,很多人覺得演算法很難,沒錯,但是世界上真的有很難的事情嗎?如果不去嘗試,只去抱怨,不去嘗試,我覺得可能一輩子也就只能當一名普通的程式設計師了。有一句老話說的挺好,成功的人遇到乙個難題,第一反應是想著怎麼解決它,而不是先擔心不會做,做不懂,如果不邁出第一步,後面只會更加難過。博主是個多愁善感的程式猿,不過我覺得有些東西,不該逃避的絕對不能去逃避。只有勇於面對困難,才能真正去戰勝它,哈哈,感覺有點像心靈雞湯了,好吧,開始我的初級演算法學習之路了。

無論是什麼東西,總有乙個判別的標準,演算法也是,並不是說你說這個演算法好就好,界內是有乙個專門的標準的,在保證演算法的準確性後,這個判別標準就是演算法的時間複雜度,學過資料結構的同學不會對此陌生,評價乙個演算法流程的好壞,是先看時間複雜度的指標,我們在然後再分析不同資料樣本下的實際執行時間,也就是常數項時間。

通常我們一般使用o(讀作big 歐 )來表示,具體來說,在常數運算元量的表示式中,只要高階項,不要低階項,也不要高階項的係數,剩下的部分,如果記為f(n),那麼時間複雜度為o(f(n))。

一般來說,我們談論演算法的速度所指的並非是時間,而是運算元的增速,這一點我們可以把 f(n) 的曲線圖畫出來就會十分的清晰,隨著輸入的增加,執行時間將以什麼樣的速度增加才是我們真正關注的,且演算法執行時間並不以秒作為單位,可能是次數、時間等

下面我用上家公司的一道面試演算法題來大致說明:

題目大致是:有兩個已排序的陣列,分別是n=[ 1,2,4,5,6,7]  m=[ 2,3,5,6,9,12,15,17] ,請用原生的語言將其交集求出,假設n是乙個有n個元素的陣列,m是有m個元素的陣列,求出其演算法時間複雜度(要求,不用任何關於陣列內建方法或函式)

當初我碰到這道題的時候,就知道肯定是有多種演算法來解決的,現在看來大致有著三種,每種的演算法複雜度都不同。下面我用php語言結合**對其進行說明,(本想用c的,不過真的忘了)

第一種演算法,也是最為簡單的,兩個迴圈進行遍歷即可:

<?php 

$m = [2,3,5,6,9,12,15,17];

$n = [1,2,4,5,6,7];

$temparray = ; //臨時陣列

for($i = 0;$i < count($n); $i++)

//匹配到相等的則放入臨時陣列中

if($n[$i] ==$m[$a])

} }var_dump($temparray);

我們簡單分析一下這種簡單粗暴的方式,基本上不懂演算法的人也會用這種方式,實際上就是遍歷而已,那麼這種所謂的演算法的時間複雜度是多少呢?

這時候我們可以引入乙個概念:語言頻度

語句頻度:一條語句的重複執行次數

我們可以看出兩個迴圈的語句頻度分別為m,n,則最內層的**執行的語句頻度為m*n,那麼我們可以說這個演算法的時間複雜度為o(n*m)

第二種演算法:使用二分查詢法

什麼是二分查詢法:二分查詢也稱折半查詢(binary search),它是一種效率較高的查詢方法。但是,折半查詢要求線性表必須採用順序儲存結構,而且表中元素按關鍵字有序排列,實現的**如下:

<?php 

class test

}var_dump($temparray);

}public function serachvalue($value,$arr=)

elseif($value < $arr[$middle])else}}

} $c = new test();

$c->index();

二分查詢的要求是資料結構必須是順序儲存的,而且是有序化的,從小到大或者從大到小都可以,以3在陣列 m=[2,3,5,6,9,12,15,17]查詢為例,主要是如下的步驟:

①:一開始,low為0,high為7,則middle為intval((low+high)/2) = 4  ,則 3 < $m[4]  ,故high = middle-1 = 3

②: low 為0 ,high為3,middle為intval((low+high)/2) = 2 ,則 3 < $m[3] ,故high = middle -1 = 1

③:low為0 ,high為1,middle為intval((low+high)/2) = 1,則 3 = $m[1]  ,return $m[1] 查詢成功 假設陣列個數為m個,那麼在這個陣列查詢乙個數的時間複雜度為o(log2m),那麼在我們的這個演算法中,因為陣列已經是有序化的,那麼我們則不需要對其進行排序,而n陣列的遍歷的時間複雜度為o(n),故該演算法的時間複雜度應為 o(n)*o(log2m),相比遍歷的那個演算法,o(log2m)肯定要比o(m)小,故這種演算法相對於遍歷來說是更好的演算法。

第三種演算法是:外排的方式,這種方式就比較靈活了,我大致說下流程。

首先,先定義兩個座標變數,都分別指向陣列第乙個元素的位置,如圖,n一開始指向的是1,m指向的是2,咋們按照誰指的值小誰就移動的規定來進行,流程大致如下:

①n指向的值比m小,所以n移動,其實此時可以看出,陣列n的最小的都比陣列m的最小的還要小,那麼1肯定不在陣列m中,因為兩個陣列都是從小到大排好序的。

②n指向2, 此時n指向的值和m指向的相等,匹配成功,寫入臨時陣列,n右移

③n指向4 ,4比m指向的值2大,誰小誰動,故m右移,m指向3,同理,m還是得右移

④m指向的值為5,大於n指向的值4,說明4是找不到的,按照規定n右移

**大致如下:

<?php 

$m = [2,3,5,6,9,12,15,17,20,34];

$n = [1,2,5,6,9,12,13,34];

$temparray = ;

$m = 0;

$n = 0;

while($n < (count($n)-1)||$m < (count($m)-1))elseif($n[$n] > $m[$m])else

}var_dump($temparray);

最後我們簡單總結一下三種演算法的差異

第一種:直接遍歷,時間複雜度為o(n*m) 效果較差

第二種:使用二分法 ,時間複雜度為o(n*log2m) 效果比上個好

第三種:使用外排法 ,時間複雜度為o(n+m),效果較好

哈哈,這就是演算法的奧妙了。

演算法時間複雜度空間複雜度

演算法 是解決某一類問題的通法,即一系列清晰無歧義的計算指令。每個演算法只能解決具有特定特徵的一類問題,但乙個問題可由多個演算法解決。乙個演算法應該有以下五個方面的特性 比較演算法的優劣我們從兩個維度去進行考量 時間 空間 時間複雜度,空間複雜度 找出基本語句 演算法中執行次數最多的那條語句就是基本...

演算法 時間複雜度 空間複雜度

1 if i 1 2 a 1 result 3 4 result n 2 result 1000 1000 3 array.push a array.pop 4 map.set 1,1 map.get 1,1 在計算複雜度的時候,o 1 一般會被忽略。1 for let i 0 i n i 2 wh...

演算法的時間複雜度 空間複雜度

時間複雜度和空間複雜度是度量演算法效率的常用指標 事後統計,不常用 事前統計影響因素 演算法策略 問題規模 程式語言 質量 機器執行指令的速度 撇開軟硬體的影響,演算法執行工作量的大小只依賴於問題的規模 通常用整數n表示 乙個演算法是由控制結構 順序,分支,迴圈三種 和原操作 指固有資料型別的操作 ...