導航:首頁 > 程序命令 > 程序員的復雜演算法

程序員的復雜演算法

發布時間:2022-07-30 22:57:07

演算法 對於網路編程程序員有多重要

很重要。只有學號演算法才能更好的設計程序。雖然說演算法學的不好也能編程,但是人家用5行就能解決問題,不好的就會用15行20行才能解決。懂了么。

❷ 有沒有加密演算法提供,最好是復雜的

RSA加密演算法
該演算法於1977年由美國麻省理工學院MIT(Massachusetts Institute of Technology)的Ronal Rivest,Adi Shamir和Len Adleman三位年輕教授提出,並以三人的姓氏Rivest,Shamir和Adlernan命名為RSA演算法。該演算法利用了數論領域的一個事實,那就是雖然把兩個大質數相乘生成一個合數是件十分容易的事情,但要把一個合數分解為兩個質數卻十分困難。合數分解問題目前仍然是數學領域尚未解決的一大難題,至今沒有任何高效的分解方法。與Diffie-Hellman演算法相比,RSA演算法具有明顯的優越性,因為它無須收發雙方同時參與加密過程,且非常適合於電子函件系統的加密。

RSA演算法可以表述如下:

(1) 密鑰配製。假設m是想要傳送的報文,現任選兩個很大的質數p與q,使得:

(12-1);

選擇正整數e,使得e與(p-1)(q-1)互質;這里(p-1)(q-1)表示二者相乘。再利用輾轉相除法,求得d,使得:

(12-2);

其中x mod y是整數求余運算,其結果是x整除以y後剩餘的余數,如5 mod 3 = 2。

這樣得:

(e,n),是用於加密的公共密鑰,可以公開出去;以及

(d,n),是用於解密的專用鑰匙,必須保密。

(2) 加密過程。使用(e,n)對明文m進行加密,演算法為:

(12-3);

這里的c即是m加密後的密文。

(3) 解密過程。使用(d,n)對密文c進行解密,演算法為:

(12-4);

求得的m即為對應於密文c的明文。

RSA演算法實現起來十分簡捷,據說英國的一位程序員只用了3行Perl程序便實現了加密和解密運算。

RSA演算法建立在正整數求余運算基礎之上,同時還保持了指數運算的性質,這一點我們不難證明。例如:

(12-5);

(12-6)。

RSA公共密鑰加密演算法的核心是歐拉(Euler)函數ψ。對於正整數n,ψ(n)定義為小於n且與n互質的正整數的個數。例如ψ(6) = 2,這是因為小於6且與6互質的數有1和5共兩個數;再如ψ(7) = 6,這是因為互質數有1,2,3,5,6共6個。

歐拉在公元前300多年就發現了ψ函數的一個十分有趣的性質,那就是對於任意小於n且與n互質的正整數m,總有mψ(n) mod n = 1。例如,5ψ(6) mod 6 = 52 mod 6= 25 mod 6 =1。也就是說,在對n求余的運算下,ψ(n)指數具有周期性。

當n很小時,計算ψ(n)並不難,使用窮舉法即可求出;但當n很大時,計算ψ(n)就十分困難了,其運算量與判斷n是否為質數的情況相當。不過在特殊情況下,利用ψ函數的兩個性質,可以極大地減少運算量。

性質1:如果p是質數,則ψ(p) = (p-1)。

性質2:如果p與q均為質數,則ψ(p·q) = ψ(p)·ψ(q) = (p-1)(q-1)。

RSA演算法正是注意到這兩條性質來設計公共密鑰加密系統的,p與q的乘積n可以作為公共密鑰公布出來,而n的因子p和q則包含在專用密鑰中,可以用來解密。如果解密需要用到ψ(n),收信方由於知道因子p和q,可以方便地算出ψ(n) = (p-1)(q-1)。如果竊聽者竊得了n,但由於不知道它的因子p與q,則很難求出ψ(n)。這時,竊聽者要麼強行算出ψ(n),要麼對n進行因數分解求得p與q。然而,我們知道,在大數范圍內作合數分解是十分困難的,因此竊密者很難成功。

有了關於ψ函數的認識,我們再來分析RSA演算法的工作原理:

(1) 密鑰配製。設m是要加密的信息,任選兩個大質數p與q,使得 ;選擇正整數e,使得e與ψ(n) = (p-1)(q-1)互質。

利用輾轉相除法,計算d,使得ed mod ψ(n) = ,即ed = kψ(n) +1,其中k為某一正整數。

公共密鑰為(e,n),其中沒有包含任何有關n的因子p和q的信息。

專用密鑰為(d,n),其中d隱含有因子p和q的信息。

(2) 加密過程。使用公式(12-3)對明文m進行加密,得密文c。

(3) 解密過程。使用(d,n)對密文c進行解密,計算過程為:

cd mod n = (me mod n)d mod n

= med mod n

= m(kψ(n) + 1) mod n

= (mkψ(n) mod n)·(m mod n)

= m

m即為從密文c中恢復出來的明文。

例如,假設我們需要加密的明文代碼信息為m = 14,則:

選擇e = 3,p = 5,q = 11;

計算出n = p·q = 55,(p-1)(q-1) = 40,d = 27;

可以驗證:(e·d) mod (p-1)(q-1) = 81 mod 40 = 1;

加密:c = me mod n = 143 mod 55 = 49;

解密:m = cd mod n = 4927 mod 55 = 14。

關於RSA演算法,還有幾點需要進一步說明:

(1) 之所以要求e與(p-1)(q-1)互質,是為了保證 ed mod (p-1)(q-1)有解。

(2) 實際操作時,通常先選定e,再找出並確定質數p和q,使得計算出d後它們能滿足公式(12-3)。常用的e有3和65537,這兩個數都是費馬序列中的數。費馬序列是以17世紀法國數學家費馬命名的序列。

(3) 破密者主要通過將n分解成p·q的辦法來解密,不過目前還沒有辦法證明這是唯一的辦法,也可能有更有效的方法,因為因數分解問題畢竟是一個不斷發展的領域,自從RSA演算法發明以來,人們已經發現了不少有效的因數分解方法,在一定程度上降低了破譯RSA演算法的難度,但至今還沒有出現動搖RSA演算法根基的方法。

(4) 在RSA演算法中,n的長度是控制該演算法可靠性的重要因素。目前129位、甚至155位的RSA加密勉強可解,但目前大多數加密程序均採用231、308甚至616位的RSA演算法,因此RSA加密還是相當安全的。

據專家測算,攻破512位密鑰RSA演算法大約需要8個月時間;而一個768位密鑰RSA演算法在2004年之前無法攻破。現在,在技術上還無法預測攻破具有2048位密鑰的RSA加密演算法需要多少時間。美國Lotus公司懸賞1億美元,獎勵能破譯其Domino產品中1024位密鑰的RSA演算法的人。從這個意義上說,遵照SET協議開發的電子商務系統是絕對安全的。

另MD5加密演算法:
1、MD5演算法是對輸入的數據進行補位,使得如果數據位長度LEN對512求余的結果
是448。
即數據擴展至K*512+448位。即K*64+56個位元組,K為整數。
具體補位操作:補一個1,然後補0至滿足上述要求
2、補數據長度:
用一個64位的數字表示數據的原始長度B,把B用兩個32位數表示。這時,數據
就被填
補成長度為512位的倍數。
3.初始化MD5參數
四個32位整數(A,B,C,D)用來計算信息摘要,初始化使用的是十六進製表示
的數字
A=0X01234567
B=0X89abcdef
C=0Xfedcba98
D=0X76543210
4、處理位操作函數
X,Y,Z為32位整數。
F(X,Y,Z)=X&Y|NOT(X)&Z
G(X,Y,Z)=X&Z|Y¬(Z)
H(X,Y,Z)=XxorYxorZ
I(X,Y,Z)=Yxor(X|not(Z))
5、主要變換過程:
使用常數組T[1...64],T[i]為32位整數用16進製表示,數據用16個32位的

數數組M[]表示。
具體過程如下:
/*處理數據原文*/
Fori=0toN/16-1do
/*每一次,把數據原文存放在16個元素的數組X中.*/
Forj=0to15do
SetX[j]toM[i*16+j].
end /結束對J的循環
/*SaveAasAA,BasBB,CasCC,andDasDD.*/
AA=A
BB=B
CC=C
DD=D
/*第1輪*/
/*以[abcdksi]表示如下操作
a=b+((a+F(b,c,d)+X[k]+T[i])<<<s).*/
/*Dothefollowing16operations.*/
[ABCD071][DABC1122][CDAB2173][BCDA3224]
[ABCD475][DABC5126][CDAB6177][BCDA7228]
[ABCD879][DABC91210][CDAB101711][BCDA112212]
[ABCD12713][DABC131214][CDAB141715][BCDA152216]
/*第2輪**/
/*以[abcdksi]表示如下操作
a=b+((a+G(b,c,d)+X[k]+T[i])<<<s).*/
/*Dothefollowing16operations.*/
[ABCD1517][DABC6918][CDAB111419][BCDA02020]
[ABCD5521][DABC10922][CDAB151423][BCDA42024]
[ABCD9525][DABC14926][CDAB31427][BCDA82028]
[ABCD13529][DABC2930][CDAB71431][BCDA122032]
/*第3輪*/
/*以[abcdksi]表示如下操作
a=b+((a+H(b,c,d)+X[k]+T[i])<<<s).*/
/*Dothefollowing16operations.*/
[ABCD5433][DABC81134][CDAB111635][BCDA142336]
[ABCD1437][DABC41138][CDAB71639][BCDA102340]
[ABCD13441][DABC01142][CDAB31643][BCDA62344]
[ABCD9445][DABC121146][CDAB151647][BCDA22348]
/*第4輪*/
/*以[abcdksi]表示如下操作
a=b+((a+I(b,c,d)+X[k]+T[i])<<<s).*/
/*Dothefollowing16operations.*/
[ABCD0649][DABC71050][CDAB141551][BCDA52152]
[ABCD12653][DABC31054][CDAB101555][BCDA12156]
[ABCD8657][DABC151058][CDAB61559][BCDA132160]
[ABCD4661][DABC111062][CDAB21563][BCDA92164]
/*然後進行如下操作*/
A=A+AA
B=B+BB
C=C+CC
D=D+DD
end/*結束對I的循環*/
6、輸出結果。

❸ 演算法的空間復雜度和時間復雜度的關系

論壇

活動

招聘

專題

打開CSDN APP
Copyright © 1999-2020, CSDN.NET, All Rights Reserved

搜索博文/帖子/用戶
登錄

zolalad
關注
演算法的時間復雜度和空間復雜度-總結 原創
2013-09-20 16:01:26
308點贊

zolalad

碼齡9年

關注
演算法的時間復雜度和空間復雜度-總結
通常,對於一個給定的演算法,我們要做 兩項分析。第一是從數學上證明演算法的正確性,這一步主要用到形式化證明的方法及相關推理模式,如循環不變式、數學歸納法等。而在證明演算法是正確的基礎上,第二部就是分析演算法的時間復雜度。演算法的時間復雜度反映了程序執行時間隨輸入規模增長而增長的量級,在很大程度上能很好反映出演算法的優劣與否。因此,作為程序員,掌握基本的演算法時間復雜度分析方法是很有必要的。
演算法執行時間需通過依據該演算法編制的程序在計算機上運行時所消耗的時間來度量。而度量一個程序的執行時間通常有兩種方法。

一、事後統計的方法

這種方法可行,但不是一個好的方法。該方法有兩個缺陷:一是要想對設計的演算法的運行性能進行評測,必須先依據演算法編制相應的程序並實際運行;二是所得時間的統計量依賴於計算機的硬體、軟體等環境因素,有時容易掩蓋演算法本身的優勢。

二、事前分析估算的方法

因事後統計方法更多的依賴於計算機的硬體、軟體等環境因素,有時容易掩蓋演算法本身的優劣。因此人們常常採用事前分析估算的方法。

在編寫程序前,依據統計方法對演算法進行估算。一個用高級語言編寫的程序在計算機上運行時所消耗的時間取決於下列因素:

(1). 演算法採用的策略、方法;(2). 編譯產生的代碼質量;(3). 問題的輸入規模;(4). 機器執行指令的速度。

一個演算法是由控制結構(順序、分支和循環3種)和原操作(指固有數據類型的操作)構成的,則演算法時間取決於兩者的綜合效果。為了便於比較同一個問題的不同演算法,通常的做法是,從演算法中選取一種對於所研究的問題(或演算法類型)來說是基本操作的原操作,以該基本操作的重復執行的次數作為演算法的時間量度。

1、時間復雜度
(1)時間頻度 一個演算法執行所耗費的時間,從理論上是不能算出來的,必須上機運行測試才能知道。但我們不可能也沒有必要對每個演算法都上機測試,只需知道哪個演算法花費的時間多,哪個演算法花費的時間少就可以了。並且一個演算法花費的時間與演算法中語句的執行次數成正比例,哪個演算法中語句執行次數多,它花費時間就多。一個演算法中的語句執行次數稱為語句頻度或時間頻度。記為T(n)。
(2)時間復雜度 在剛才提到的時間頻度中,n稱為問題的規模,當n不斷變化時,時間頻度T(n)也會不斷變化。但有時我們想知道它變化時呈現什麼規律。為此,我們引入時間復雜度概念。 一般情況下,演算法中基本操作重復執行的次數是問題規模n的某個函數,用T(n)表示,若有某個輔助函數f(n),使得當n趨近於無窮大時,T(n)/f(n)的極限值為不等於零的常數,則稱f(n)是T(n)的同數量級函數。記作T(n)=O(f(n)),稱O(f(n)) 為演算法的漸進時間復雜度,簡稱時間復雜度。

另外,上面公式中用到的 Landau符號其實是由德國數論學家保羅·巴赫曼(Paul Bachmann)在其1892年的著作《解析數論》首先引入,由另一位德國數論學家艾德蒙·朗道(Edmund Landau)推廣。Landau符號的作用在於用簡單的函數來描述復雜函數行為,給出一個上或下(確)界。在計算演算法復雜度時一般只用到大O符號,Landau符號體系中的小o符號、Θ符號等等比較不常用。這里的O,最初是用大寫希臘字母,但現在都用大寫英語字母O;小o符號也是用小寫英語字母o,Θ符號則維持大寫希臘字母Θ。
T (n) = Ο(f (n)) 表示存在一個常數C,使得在當n趨於正無窮時總有 T (n) ≤ C * f(n)。簡單來說,就是T(n)在n趨於正無窮時最大也就跟f(n)差不多大。也就是說當n趨於正無窮時T (n)的上界是C * f(n)。其雖然對f(n)沒有規定,但是一般都是取盡可能簡單的函數。例如,O(2n2+n +1) = O (3n2+n+3) = O (7n2 + n) = O ( n2 ) ,一般都只用O(n2)表示就可以了。注意到大O符號里隱藏著一個常數C,所以f(n)里一般不加系數。如果把T(n)當做一棵樹,那麼O(f(n))所表達的就是樹干,只關心其中的主幹,其他的細枝末節全都拋棄不管。
在各種不同演算法中,若演算法中語句執行次數為一個常數,則時間復雜度為O(1),另外,在時間頻度不相同時,時間復雜度有可能相同,如T(n)=n2+3n+4與T(n)=4n2+2n+1它們的頻度不同,但時間復雜度相同,都為O(n2)。 按數量級遞增排列,常見的時間復雜度有:常數階O(1),對數階O(log2n),線性階O(n), 線性對數階O(nlog2n),平方階O(n2),立方階O(n3),..., k次方階O(nk),指數階O(2n)。隨著問題規模n的不斷增大,上述時間復雜度不斷增大,演算法的執行效率越低。

從圖中可見,我們應該盡可能選用多項式階O(nk)的演算法,而不希望用指數階的演算法。

常見的演算法時間復雜度由小到大依次為:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)

一般情況下,對一個問題(或一類演算法)只需選擇一種基本操作來討論演算法的時間復雜度即可,有時也需要同時考慮幾種基本操作,甚至可以對不同的操作賦予不同的權值,以反映執行不同操作所需的相對時間,這種做法便於綜合比較解決同一問題的兩種完全不同的演算法。

(3)求解演算法的時間復雜度的具體步驟是:

⑴ 找出演算法中的基本語句;

演算法中執行次數最多的那條語句就是基本語句,通常是最內層循環的循環體。

⑵ 計算基本語句的執行次數的數量級;

只需計算基本語句執行次數的數量級,這就意味著只要保證基本語句執行次數的函數中的最高次冪正確即可,可以忽略所有低次冪和最高次冪的系數。這樣能夠簡化演算法分析,並且使注意力集中在最重要的一點上:增長率。

⑶ 用大Ο記號表示演算法的時間性能。

將基本語句執行次數的數量級放入大Ο記號中。

如果演算法中包含嵌套的循環,則基本語句通常是最內層的循環體,如果演算法中包含並列的循環,則將並列循環的時間復雜度相加。例如:

for (i=1; i<=n; i++)
x++;
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
x++;
第一個for循環的時間復雜度為Ο(n),第二個for循環的時間復雜度為Ο(n2),則整個演算法的時間復雜度為Ο(n+n2)=Ο(n2)。

Ο(1)表示基本語句的執行次數是一個常數,一般來說,只要演算法中不存在循環語句,其時間復雜度就是Ο(1)。其中Ο(log2n)、Ο(n)、 Ο(nlog2n)、Ο(n2)和Ο(n3)稱為多項式時間,而Ο(2n)和Ο(n!)稱為指數時間。計算機科學家普遍認為前者(即多項式時間復雜度的演算法)是有效演算法,把這類問題稱為P(Polynomial,多項式)類問題,而把後者(即指數時間復雜度的演算法)稱為NP(Non-Deterministic Polynomial, 非確定多項式)問題。

一般來說多項式級的復雜度是可以接受的,很多問題都有多項式級的解——也就是說,這樣的問題,對於一個規模是n的輸入,在n^k的時間內得到結果,稱為P問題。有些問題要復雜些,沒有多項式時間的解,但是可以在多項式時間里驗證某個猜測是不是正確。比如問4294967297是不是質數?如果要直接入手的話,那麼要把小於4294967297的平方根的所有素數都拿出來,看看能不能整除。還好歐拉告訴我們,這個數等於641和6700417的乘積,不是素數,很好驗證的,順便麻煩轉告費馬他的猜想不成立。大數分解、Hamilton迴路之類的問題,都是可以多項式時間內驗證一個「解」是否正確,這類問題叫做NP問題。

(4)在計算演算法時間復雜度時有以下幾個簡單的程序分析法則:

(1).對於一些簡單的輸入輸出語句或賦值語句,近似認為需要O(1)時間

(2).對於順序結構,需要依次執行一系列語句所用的時間可採用大O下"求和法則"

求和法則:是指若演算法的2個部分時間復雜度分別為 T1(n)=O(f(n))和 T2(n)=O(g(n)),則 T1(n)+T2(n)=O(max(f(n), g(n)))

特別地,若T1(m)=O(f(m)), T2(n)=O(g(n)),則 T1(m)+T2(n)=O(f(m) + g(n))

(3).對於選擇結構,如if語句,它的主要時間耗費是在執行then字句或else字句所用的時間,需注意的是檢驗條件也需要O(1)時間

(4).對於循環結構,循環語句的運行時間主要體現在多次迭代中執行循環體以及檢驗循環條件的時間耗費,一般可用大O下"乘法法則"

乘法法則: 是指若演算法的2個部分時間復雜度分別為 T1(n)=O(f(n))和 T2(n)=O(g(n)),則 T1*T2=O(f(n)*g(n))

(5).對於復雜的演算法,可以將它分成幾個容易估算的部分,然後利用求和法則和乘法法則技術整個演算法的時間復雜度

另外還有以下2個運演算法則:(1) 若g(n)=O(f(n)),則O(f(n))+ O(g(n))= O(f(n));(2) O(Cf(n)) = O(f(n)),其中C是一個正常數

(5)下面分別對幾個常見的時間復雜度進行示例說明:

(1)、O(1)

Temp=i; i=j; j=temp;

以上三條單個語句的頻度均為1,該程序段的執行時間是一個與問題規模n無關的常數。演算法的時間復雜度為常數階,記作T(n)=O(1)。注意:如果演算法的執行時間不隨著問題規模n的增加而增長,即使演算法中有上千條語句,其執行時間也不過是一個較大的常數。此類演算法的時間復雜度是O(1)。
(2)、O(n2)

2.1. 交換i和j的內容

sum=0; (一次)
for(i=1;i<=n;i++) (n+1次)
for(j=1;j<=n;j++) (n2次)
sum++; (n2次)
解:因為Θ(2n2+n+1)=n2(Θ即:去低階項,去掉常數項,去掉高階項的常參得到),所以T(n)= =O(n2);

2.2.

for (i=1;i<n;i++)
{
y=y+1; ①
for (j=0;j<=(2*n);j++)
x++; ②
}
解: 語句1的頻度是n-1
語句2的頻度是(n-1)*(2n+1)=2n2-n-1
f(n)=2n2-n-1+(n-1)=2n2-2;

又Θ(2n2-2)=n2
該程序的時間復雜度T(n)=O(n2).

一般情況下,對步進循環語句只需考慮循環體中語句的執行次數,忽略該語句中步長加1、終值判別、控制轉移等成分,當有若干個循環語句時,演算法的時間復雜度是由嵌套層數最多的循環語句中最內層語句的頻度f(n)決定的。

(3)、O(n)

a=0;
b=1; ①
for (i=1;i<=n;i++) ②
{
s=a+b;③
b=a;④
a=s;⑤
}
解: 語句1的頻度:2,
語句2的頻度: n,
語句3的頻度: n-1,
語句4的頻度:n-1,
語句5的頻度:n-1,
T(n)=2+n+3(n-1)=4n-1=O(n).
(4)、O(log2n)

i=1; ①
while (i<=n)
i=i*2; ②
解: 語句1的頻度是1,
設語句2的頻度是f(n), 則:2^f(n)<=n;f(n)<=log2n
取最大值f(n)=log2n,
T(n)=O(log2n )

(5)、O(n3)

for(i=0;i<n;i++)
{
for(j=0;j<i;j++)
{
for(k=0;k<j;k++)
x=x+2;
}
}
解:當i=m, j=k的時候,內層循環的次數為k當i=m時, j 可以取 0,1,...,m-1 , 所以這里最內循環共進行了0+1+...+m-1=(m-1)m/2次所以,i從0取到n, 則循環共進行了: 0+(1-1)*1/2+...+(n-1)n/2=n(n+1)(n-1)/6所以時間復雜度為O(n3).

(5)常用的演算法的時間復雜度和空間復雜度

一個經驗規則:其中c是一個常量,如果一個演算法的復雜度為c 、 log2n 、n 、 n*log2n ,那麼這個演算法時間效率比較高 ,如果是2n ,3n ,n!,那麼稍微大一些的n就會令這個演算法不能動了,居於中間的幾個則差強人意。

演算法時間復雜度分析是一個很重要的問題,任何一個程序員都應該熟練掌握其概念和基本方法,而且要善於從數學層面上探尋其本質,才能准確理解其內涵。

2、演算法的空間復雜度

類似於時間復雜度的討論,一個演算法的空間復雜度(Space Complexity)S(n)定義為該演算法所耗費的存儲空間,它也是問題規模n的函數。漸近空間復雜度也常常簡稱為空間復雜度。
空間復雜度(Space Complexity)是對一個演算法在運行過程中臨時佔用存儲空間大小的量度。一個演算法在計算機存儲器上所佔用的存儲空間,包括存儲演算法本身所佔用的存儲空間,演算法的輸入輸出數據所佔用的存儲空間和演算法在運行過程中臨時佔用的存儲空間這三個方面。演算法的輸入輸出數據所佔用的存儲空間是由要解決的問題決定的,是通過參數表由調用函數傳遞而來的,它不隨本演算法的不同而改變。存儲演算法本身所佔用的存儲空間與演算法書寫的長短成正比,要壓縮這方面的存儲空間,就必須編寫出較短的演算法。演算法在運行過程中臨時佔用的存儲空間隨演算法的不同而異,有的演算法只需要佔用少量的臨時工作單元,而且不隨問題規模的大小而改變,我們稱這種演算法是「就地\"進行的,是節省存儲的演算法,如這一節介紹過的幾個演算法都是如此;有的演算法需要佔用的臨時工作單元數與解決問題的規模n有關,它隨著n的增大而增大,當n較大時,將佔用較多的存儲單元,例如將在第九章介紹的快速排序和歸並排序演算法就屬於這種情況。

如當一個演算法的空間復雜度為一個常量,即不隨被處理數據量n的大小而改變時,可表示為O(1);當一個演算法的空間復雜度與以2為底的n的對數成正比時,可表示為0(10g2n);當一個演算法的空I司復雜度與n成線性比例關系時,可表示為0(n).若形參為數組,則只需要為它分配一個存儲由實參傳送來的一個地址指針的空間,即一個機器字長空間;若形參為引用方式,則也只需要為其分配存儲一個地址的空間,用它來存儲對應實參變數的地址,

❹ 作為程序員提高編程能力的幾個基礎演算法

一:快速排序演算法

快速排序是由東尼·霍爾所發展的一種排序演算法。在平均狀況下,排序n個項目要Ο(nlogn)次比較。在最壞狀況下則需要Ο(n2)次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他Ο(nlogn)演算法更快,因為它的內部循環(innerloop)可以在大部分的架構上很有效率地被實現出來。

快速排序使用分治法(Divideandconquer)策略來把一個串列(list)分為兩個子串列(sub-lists)。

演算法步驟:

1從數列中挑出一個元素,稱為「基準」(pivot),

2重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分區退出之後,該基準就處於數列的中間位置。這個稱為分區(partition)操作。

3遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。

遞歸的最底部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞歸下去,但是這個演算法總會退出,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它最後的位置去。

二:堆排序演算法

堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序演算法。堆積是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。

堆排序的平均時間復雜度為Ο(nlogn) 。

創建一個堆H[0..n-1]

把堆首(最大值)和堆尾互換

3.把堆的尺寸縮小1,並調用shift_down(0),目的是把新的數組頂端數據調整到相應位置

4.重復步驟2,直到堆的尺寸為1

三:歸並排序

歸並排序(Mergesort,台灣譯作:合並排序)是建立在歸並操作上的一種有效的排序演算法。該演算法是採用分治法(DivideandConquer)的一個非常典型的應用。

1.申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合並後的序列

2.設定兩個指針,最初位置分別為兩個已經排序序列的起始位置

3.比較兩個指針所指向的元素,選擇相對小的元素放入到合並空間,並移動指針到下一位置

4.重復步驟3直到某一指針達到序列尾

5.將另一序列剩下的所有元素直接復制到合並序列尾

四:二分查找演算法

二分查找演算法是一種在有序數組中查找某一特定元素的搜索演算法。搜素過程從數組的中間元素開始,如果中間元素正好是要查找的元素,則搜素過程結束;如果某一特定元素大於或者小於中間元素,則在數組大於或小於中間元素的那一半中查找,而且跟開始一樣從中間元素開始比較。如果在某一步驟數組為空,則代表找不到。這種搜索演算法每一次比較都使搜索范圍縮小一半。折半搜索每次把搜索區域減少一半,時間復雜度為Ο(logn) 。

五:BFPRT(線性查找演算法)

BFPRT演算法解決的問題十分經典,即從某n個元素的序列中選出第k大(第k小)的元素,通過巧妙的分析,BFPRT可以保證在最壞情況下仍為線性時間復雜度。該演算法的思想與快速排序思想相似,當然,為使得演算法在最壞情況下,依然能達到o(n)的時間復雜度,五位演算法作者做了精妙的處理。

1.將n個元素每5個一組,分成n/5(上界)組。

2.取出每一組的中位數,任意排序方法,比如插入排序。

3.遞歸的調用selection演算法查找上一步中所有中位數的中位數,設為x,偶數個中位數的情況下設定為選取中間小的一個。

4.用x來分割數組,設小於等於x的個數為k,大於x的個數即為n-k。

5.若i==k,返回x;若i<k,在小於x的元素中遞歸查找第i小的元素;若i>k,在大於x的元素中遞歸查找第i-k小的元素。

終止條件:n=1時,返回的即是i小元素。

六:DFS(深度優先搜索)

深度優先搜索演算法(Depth-First-Search),是搜索演算法的一種。它沿著樹的深度遍歷樹的節點,盡可能深的搜索樹的分支。當節點v的所有邊都己被探尋過,搜索將回溯到發現節點v的那條邊的起始節點。這一過程一直進行到已發現從源節點可達的所有節點為止。如果還存在未被發現的節點,則選擇其中一個作為源節點並重復以上過程,整個進程反復進行直到所有節點都被訪問為止。DFS屬於盲目搜索。

深度優先搜索是圖論中的經典演算法,利用深度優先搜索演算法可以產生目標圖的相應拓撲排序表,利用拓撲排序表可以方便的解決很多相關的圖論問題,如最大路徑問題等等。一般用堆數據結構來輔助實現DFS演算法。

深度優先遍歷圖演算法步驟:

1.訪問頂點v;

2.依次從v的未被訪問的鄰接點出發,對圖進行深度優先遍歷;直至圖中和v有路徑相通的頂點都被訪問;

3.若此時圖中尚有頂點未被訪問,則從一個未被訪問的頂點出發,重新進行深度優先遍歷,直到圖中所有頂點均被訪問過為止。

上述描述可能比較抽象,舉個實例:

DFS在訪問圖中某一起始頂點v後,由v出發,訪問它的任一鄰接頂點w1;再從w1出發,訪問與w1鄰接但還沒有訪問過的頂點w2;然後再從w2出發,進行類似的訪問,…如此進行下去,直至到達所有的鄰接頂點都被訪問過的頂點u為止。

接著,退回一步,退到前一次剛訪問過的頂點,看是否還有其它沒有被訪問的鄰接頂點。如果有,則訪問此頂點,之後再從此頂點出發,進行與前述類似的訪問;如果沒有,就再退回一步進行搜索。重復上述過程,直到連通圖中所有頂點都被訪問過為止。

七:BFS(廣度優先搜索)

廣度優先搜索演算法(Breadth-First-Search),是一種圖形搜索演算法。簡單的說,BFS是從根節點開始,沿著樹(圖)的寬度遍歷樹(圖)的節點。如果所有節點均被訪問,則演算法中止。

BFS同樣屬於盲目搜索。一般用隊列數據結構來輔助實現BFS演算法。

1.首先將根節點放入隊列中。

2.從隊列中取出第一個節點,並檢驗它是否為目標。

如果找到目標,則結束搜尋並回傳結果。

否則將它所有尚未檢驗過的直接子節點加入隊列中。

3.若隊列為空,表示整張圖都檢查過了——亦即圖中沒有欲搜尋的目標。結束搜尋並回傳「找不到目標」。

4.重復步驟2。

八:Dijkstra演算法

戴克斯特拉演算法(Dijkstra』salgorithm)是由荷蘭計算機科學家艾茲赫爾·戴克斯特拉提出。迪科斯徹演算法使用了廣度優先搜索解決非負權有向圖的單源最短路徑問題,演算法最終得到一個最短路徑樹。該演算法常用於路由演算法或者作為其他圖演算法的一個子模塊。

該演算法的輸入包含了一個有權重的有向圖G,以及G中的一個來源頂點S。我們以V表示G中所有頂點的集合。每一個圖中的邊,都是兩個頂點所形成的有序元素對。(u,v)表示從頂點u到v有路徑相連。我們以E表示G中所有邊的集合,而邊的權重則由權重函數w:E→[0,∞]定義。因此,w(u,v)就是從頂點u到頂點v的非負權重(weight)。邊的權重可以想像成兩個頂點之間的距離。任兩點間路徑的權重,就是該路徑上所有邊的權重總和。已知有V中有頂點s及t,Dijkstra演算法可以找到s到t的最低權重路徑(例如,最短路徑)。這個演算法也可以在一個圖中,找到從一個頂點s到任何其他頂點的最短路徑。對於不含負權的有向圖,Dijkstra演算法是目前已知的最快的單源最短路徑演算法。

1.初始時令S=,T=,T中頂點對應的距離值

若存在<V0,Vi>,d(V0,Vi)為<V0,Vi>弧上的權值

若不存在<V0,Vi>,d(V0,Vi)為∞

2.從T中選取一個其距離值為最小的頂點W且不在S中,加入S

3.對其餘T中頂點的距離值進行修改:若加進W作中間頂點,從V0到Vi的距離值縮短,則修改此距離值

重復上述步驟2、3,直到S中包含所有頂點,即W=Vi為止

九:動態規劃演算法

動態規劃(Dynamicprogramming)是一種在數學、計算機科學和經濟學中使用的,通過把原問題分解為相對簡單的子問題的方式求解復雜問題的方法。動態規劃常常適用於有重疊子問題和最優子結構性質的問題,動態規劃方法所耗時間往往遠少於樸素解法。

動態規劃背後的基本思想非常簡單。大致上,若要解一個給定問題,我們需要解其不同部分(即子問題),再合並子問題的解以得出原問題的解。通常許多子問題非常相似,為此動態規劃法試圖僅僅解決每個子問題一次,從而減少計算量:一旦某個給定子問題的解已經算出,則將其記憶化存儲,以便下次需要同一個子問題解之時直接查表。這種做法在重復子問題的數目關於輸入的規模呈指數增長時特別有用。

關於動態規劃最經典的問題當屬背包問題。

1.最優子結構性質。如果問題的最優解所包含的子問題的解也是最優的,我們就稱該問題具有最優子結構性質(即滿足最優化原理)。最優子結構性質為動態規劃演算法解決問題提供了重要線索。

2.子問題重疊性質。子問題重疊性質是指在用遞歸演算法自頂向下對問題進行求解時,每次產生的子問題並不總是新問題,有些子問題會被重復計算多次。動態規劃演算法正是利用了這種子問題的重疊性質,對每一個子問題只計算一次,然後將其計算結果保存在一個表格中,當再次需要計算已經計算過的子問題時,只是在表格中簡單地查看一下結果,從而獲得較高的效率。

十:樸素貝葉斯分類演算法

樸素貝葉斯分類演算法是一種基於貝葉斯定理的簡單概率分類演算法。貝葉斯分類的基礎是概率推理,就是在各種條件的存在不確定,僅知其出現概率的情況下,如何完成推理和決策任務。概率推理是與確定性推理相對應的。而樸素貝葉斯分類器是基於獨立假設的,即假設樣本每個特徵與其他特徵都不相關。

樸素貝葉斯分類器依靠精確的自然概率模型,在有監督學習的樣本集中能獲取得非常好的分類效果。在許多實際應用中,樸素貝葉斯模型參數估計使用最大似然估計方法,換言樸素貝葉斯模型能工作並沒有用到貝葉斯概率或者任何貝葉斯模型。

盡管是帶著這些樸素思想和過於簡單化的假設,但樸素貝葉斯分類器在很多復雜的現實情形中仍能夠取得相當好的效果。

通過掌握以上演算法,能夠幫你迅速提高編程能力,成為一名優秀的程序員。

❺ 求編程領域上一些經典演算法同時也是程序員必須掌握的演算法

這是我在一個論壇里看到的,你也參考參考吧。C++的虛函數
======================
C++使用虛函數實現了其對象的多態,C++對象的開始四個位元組是指向虛函數表的指針,其初始化順序是先基類後派生類,所以該虛函數表永遠指向最後一個派生類,從而實現了相同函數在不同對象中的不同行為,使得對象既有共性,又有其個性。

內存池分配、回收之夥伴演算法
=======================
夥伴演算法是空閑鏈表法的一個增強演算法,依次建立2^0\2^1\2^2\2^3...2^n大小的 內存塊空閑鏈表,利用相鄰內存塊的夥伴性質,很容易將互為夥伴的內存塊進行合並移到相應的空閑鏈表或將一塊內存拆分成兩塊夥伴內存,一塊分配出去,另一塊掛入相應空閑鏈表,使得內存的分配和回收變得高效。

AVL樹
=======================
AVL樹是一個平衡二叉樹,其中序遍歷是從小到大排序的,該結構插入節點和檢索非常高效,被廣泛應用

快速排序
=======================
通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。效率非常高

密碼學之非對稱加密協議(公鑰、私鑰加密協議)
======================
非對稱加密演算法需要兩個密鑰,用其中一個加密產生的密文,只能通過另外一個密鑰解密,密鑰持有者A可以將其中一個公開,稱為公用密鑰,另外一個秘密保存稱為私鑰,這樣當某人B想給A傳一封秘信時,只要將密信使用A的公鑰加密後,就可以放心使用各種信道將迷信傳給A了,因為該密信只有A可以解密,第三者截取因為無法解密而毫無意義。
該演算法很好地解決了密鑰的安全傳遞的問題,因為公鑰和加密演算法都是公開的,私鑰不需要傳輸。

密碼學之數字簽名協議(身份鑒別、防抵賴)
======================
數字簽名也是建立在非對稱加密基礎之上的,如果A君用它的私鑰將文件加密後在發布,A君就無法抵賴該文件是其發布的,因為其他人能通過A君的公鑰將文件解密就說明,如果演算法可靠,該文件一定是A君用其私鑰加密的。
由於非對稱加密演算法的加密和解密很慢,現在的數字簽名並非是將其要發布的信息用其私鑰加密,而是先用一個單項散列演算法如(MD5)產生一個該信息的比較短的指紋(hash值),對其指紋用其私鑰加密後和信息一並發布,同樣達到了防抵賴的作用。

無回溯字元串模式匹配-kmp演算法
======================
他是根據子串的特徵,當匹配失敗時,不需要回溯,而是直接將字串向後滑動若干個位元組,繼續匹配,極大提高了匹配速度。該演算法被廣泛使用。詳細請參考數據結構教程。

最小路徑選路-迪傑斯特拉演算法、弗洛伊德演算法
======================
學習數據結構的時候,印象最深的就要算kmp演算法和最小路徑演算法了,因為理解他們比較費腦子,我是不可能發明這些演算法了,發明他們的都是天才,呵呵。
使用最短路徑的演算法曾經幫人寫過一個小東西,還是很有效的,記得是使用的弗洛伊德演算法的一個變種,要詳細了解的朋友可以查找相關資料,想將他們使用在你的項目中,代碼直接從教科書上抄就可以了,不需要理解。

tcp協議之-nagle演算法
======================
tcp、ip中令人叫絕的想法很多,印象最深的要算nagle演算法了。
tcp出於效率和流量控制的考慮,發送端的數據不是產生多少就馬上發送多少,一般是等到數據集聚到發送緩沖區長度的一半或者數據達到最大tcp數據包數據部分長度(好像是65515)才啟動發送,而且還要看接受端可用緩沖區的大小,如果接受端產生一個回應報文通知發送端沒有接受空間了,發送端哪怕緩沖區已經滿了,也不會啟動發送,直到接受端通告發送端其已經有了接受數據的空間了。
這樣就有一個問題,假如發送端就是要發送一個小報文(比如10個位元組),然後等待對方的回應。按照上面的方案,tcp會一直等數據收集到一定量才發送,於是矛盾就產生了。應用層不再發數據,tcp等不到足夠的數據不會將10個字的數據發送到網卡,接收端應用層收不到數據就不會回應發送端。
你也可能說,可以讓修改發送端發送條件,不一定要等到足夠的數據再發送,為了效率考慮,可以考慮延時一定的時間,比如說1秒,如果上層還沒有數據到來,就將發送緩沖中的數據發出去。當然這樣也是可行的,盡管應用端白白等了1秒鍾啥也沒干,呵呵。
其實nagle演算法很好解決了該問題,它的做發是鏈接建立後的第一次發送不用等待,直接將數據組裝成tcp報文發送出去,以後要麼等到數據量足夠多、要麼是等到接受方的確認報文,演算法及其簡單,而且很好解決了上面的矛盾。

socket之io模型設計
======================
windows下socket有兩種工作方式:
1)同步方式
2)非同步方式

同步socket又有兩種工作模式:
1)阻塞模式
2)非阻塞模式

阻塞模式是最簡單的工作模式,以tcp的發送數據為例,如果發送緩沖區沒有空間,send調用就不會返回,一直要等到能夠發出一點數據為止,哪怕是一個位元組,但是send返回並不表示我要發送的數據已經全部提交給了tcp,所以send返回時要檢查這次發送的數量,調整發送緩沖指針,繼續發送,直到所有數據都提交給了系統。
由於其阻塞的特性,會阻塞發送線程,所以單線程的程序是不適合使用阻塞模式通信的,一般使用一個連接一個線程的方法,但是這種方式對於要維護多個連接的程序,是個不好的選擇,線程越多,開銷越大。

同步非阻塞模式的socket不會阻塞通信線程,如果發送緩沖區滿,send調用也是立刻返回,接受緩沖區空,recv也不會阻塞,所以通信線程要反復調用send或recv嘗試發送或接收數據,對cpu是很大的浪費。
針對非阻塞的尷尬,介面開發人員發明了三種io模型來解決該問題:
1)選擇模型(select)
2)非同步選擇模型(AsyncSelect)
3)事件選擇模型(EventSeselect)
其思想是根據io類型,預先查看1個或n個socket是否能讀、寫等。
其select本身來說,select是阻塞的,可以同時監視多個socket,只要所監視的其中一個socket可以讀、寫,secect調用才返回
非同步選擇模型其select是非同步的(非同步是不會阻塞的),是將監視任務委託給系統,系統在socket可讀、寫時通過消息通知應用程序。有一點需要說明,假如應用程序已經有很多數據需要發送,當收到可寫通知時,一定要盡量多地發送數據,直到發送失敗,lasterror提示「將要阻塞」,將來才可能有新的可寫通知到來,否則永遠也不會有。
事件選擇模型也是將監視socket狀態的工作委託給系統,系統在適當的時候通過事件通知應用程序socket可以的操作。

除了同步工作方式外,還有一種叫非同步工作方式
非同步工作方式是不會阻塞的,因為是將io操作本身委託給系統,系統在io操作完成後通過回調常式或事件或完成包通知應用程序
非同步工作方式有兩種io模型和其對應,其實這兩種模型是window是非同步io的實現:
1)重疊模型
2)完成埠

重疊模型通過事件或回調常式通知應用程序io已經完成
完成埠模型比較復雜,完成埠本身其實是一個io完成包隊列。
應用程序一般創建若干個線程用來監視完成埠,這些線程試圖從完成埠移除一個完成包,如果有,移除成功,應用程序處理該完成包,否則應用程序監視完成埠的線程被阻塞。

select模型是從UNIX上的Berkeley Software Distribution(BSD)版本的套接字就實現了的,其它四種io模型windows發明的,在windows中完成埠和非同步選擇模型是使用比較廣泛的,一般分別用於服務端和客戶端開發。
這五種io模型設計還是比較巧妙的:三種選擇模型很好解決了「同步非阻塞」模式編程的不足;重疊模型和完成埠是windows非同步io的經典實現,不局限於網路io,對文件io同樣適用。

說點題外話,socket的send完成僅僅是將數據(可能是部分)提交給系統,而不是已經發送到了網卡上,更不是已經發送到了接收端。所以要知道你的數據已經發送到了對方的應用層的唯一方法是,讓對方給你發送一個應對包。
發送數據要注意,對應tcp,要防止發送和接收的亂序,對於發送,一般應該為每一個鏈接建立一個發送隊列,採用類似nagle的演算法啟動數據發送。
一次發送可能是你提交數據的一部分,一定要當心,否則出問題沒處找去。

❻ 一個演算法的時間復雜度和其空間復雜度有何關系

一個演算法的時間復雜度和其空間復雜度的關系可這樣理解。

一個演算法要做高效率低存儲是很困難的,也就是說,演算法的時間復雜度小,可能需要較大的空間復雜度。反之亦然。也可以說,通過空間換得時間。

演算法的時間復雜度和空間復雜度可以同時很大,也可以同時很小。如T(n)=O(n)且S(n)=O(1)的情況比如一個for(i=0;i<N;i++),若循環體中為一個與問題規模無關的變數變化,則其S(n)=O(1),而T(n)=O(n)是隨著N的變化而變化的,這時可以說時間復雜度較小而空間復雜度很小。

(6)程序員的復雜演算法擴展閱讀:

一個演算法的空間復雜度只考慮在運行過程中為局部變數分配的存儲空間的大小,它包括為參數表中形參變數分配的存儲空間和為在函數體中定義的局部變數分配的存儲空間兩個部分。若一個演算法為遞歸演算法,其空間復雜度為遞歸所使用的堆棧空間的大小,它等於一次調用所分配的臨時存儲空間的大小乘以被調用的次數(即為遞歸調用的次數加1,這個1表示開始進行的一次非遞歸調用)。演算法的空間復雜度一般也以數量級的形式給出。

❼ 程序員必須掌握哪些演算法

一.基本演算法:

枚舉. (poj1753,poj2965)

貪心(poj1328,poj2109,poj2586)

遞歸和分治法.

遞推.

構造法.(poj3295)

模擬法.(poj1068,poj2632,poj1573,poj2993,poj2996)

二.圖演算法:

圖的深度優先遍歷和廣度優先遍歷.

最短路徑演算法(dijkstra,bellman-ford,floyd,heap+dijkstra)
(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)
最小生成樹演算法(prim,kruskal)
(poj1789,poj2485,poj1258,poj3026)
拓撲排序 (poj1094)

二分圖的最大匹配 (匈牙利演算法) (poj3041,poj3020)

最大流的增廣路演算法(KM演算法). (poj1459,poj3436)

三.數據結構.

串 (poj1035,poj3080,poj1936)

排序(快排、歸並排(與逆序數有關)、堆排) (poj2388,poj2299)

簡單並查集的應用.

哈希表和二分查找等高效查找法(數的Hash,串的Hash)
(poj3349,poj3274,POJ2151,poj1840,poj2002,poj2503)
哈夫曼樹(poj3253)



trie樹(靜態建樹、動態建樹) (poj2513)

四.簡單搜索

深度優先搜索 (poj2488,poj3083,poj3009,poj1321,poj2251)

廣度優先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)

簡單搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)

五.動態規劃

背包問題. (poj1837,poj1276)

型如下表的簡單DP(可參考lrj的書 page149):
E[j]=opt{D+w(i,j)} (poj3267,poj1836,poj1260,poj2533)
E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1]+zij} (最長公共子序列) (poj3176,poj1080,poj1159)
C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最優二分檢索樹問題)
六.數學

組合數學:
1.加法原理和乘法原理.
2.排列組合.
3.遞推關系.
(POJ3252,poj1850,poj1019,poj1942)
數論.
1.素數與整除問題
2.進制位.
3.同餘模運算.
(poj2635, poj3292,poj1845,poj2115)
計算方法.
1.二分法求解單調函數相關知識.(poj3273,poj3258,poj1905,poj3122)
七.計算幾何學.

幾何公式.

叉積和點積的運用(如線段相交的判定,點到線段的距離等). (poj2031,poj1039)

多邊型的簡單演算法(求面積)和相關判定(點在多邊型內,多邊型是否相交)
(poj1408,poj1584)
凸包. (poj2187,poj1113)

中級(校賽壓軸及省賽中等難度):
一.基本演算法:

C++的標准模版庫的應用. (poj3096,poj3007)

較為復雜的模擬題的訓練(poj3393,poj1472,poj3371,poj1027,poj2706)

二.圖演算法:

差分約束系統的建立和求解. (poj1201,poj2983)

最小費用最大流(poj2516,poj2516,poj2195)

雙連通分量(poj2942)

強連通分支及其縮點.(poj2186)

圖的割邊和割點(poj3352)

最小割模型、網路流規約(poj3308)

三.數據結構.

線段樹. (poj2528,poj2828,poj2777,poj2886,poj2750)

靜態二叉檢索樹. (poj2482,poj2352)

樹狀樹組(poj1195,poj3321)

RMQ. (poj3264,poj3368)

並查集的高級應用. (poj1703,2492)

KMP演算法. (poj1961,poj2406)

四.搜索

最優化剪枝和可行性剪枝

搜索的技巧和優化 (poj3411,poj1724)

記憶化搜索(poj3373,poj1691)

五.動態規劃

較為復雜的動態規劃(如動態規劃解特別的旅行商TSP問題等)
(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)
記錄狀態的動態規劃. (POJ3254,poj2411,poj1185)

樹型動態規劃(poj2057,poj1947,poj2486,poj3140)

六.數學

組合數學:
1.容斥原理.
2.抽屜原理.
3.置換群與Polya定理(poj1286,poj2409,poj3270,poj1026).
4.遞推關系和母函數.
數學.
1.高斯消元法(poj2947,poj1487, poj2065,poj1166,poj1222)
2.概率問題. (poj3071,poj3440)
3.GCD、擴展的歐幾里德(中國剩餘定理) (poj3101)
計算方法.
1.0/1分數規劃. (poj2976)
2.三分法求解單峰(單谷)的極值.
3.矩陣法(poj3150,poj3422,poj3070)
4.迭代逼近(poj3301)
隨機化演算法(poj3318,poj2454)
雜題(poj1870,poj3296,poj3286,poj1095)
七.計算幾何學.

坐標離散化.

掃描線演算法(例如求矩形的面積和周長並,常和線段樹或堆一起使用)
(poj1765,poj1177,poj1151,poj3277,poj2280,poj3004)
多邊形的內核(半平面交)(poj3130,poj3335)

幾何工具的綜合應用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)

高級(regional中等難度):
一.基本演算法要求:

代碼快速寫成,精簡但不失風格

(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)

保證正確性和高效性. poj3434

二.圖演算法:

度限制最小生成樹和第K最短路. (poj1639)

最短路,最小生成樹,二分圖,最大流問題的相關理論(主要是模型建立和求解)
(poj3155, poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446
最優比率生成樹. (poj2728)

最小樹形圖(poj3164)

次小生成樹.

無向圖、有向圖的最小環

三.數據結構.

trie圖的建立和應用. (poj2778)

LCA和RMQ問題(LCA(最近公共祖先問題) 有離線演算法(並查集+dfs) 和 在線演算法(RMQ+dfs)).(poj1330)
雙端隊列和它的應用(維護一個單調的隊列,常常在動態規劃中起到優化狀態轉移的目的). (poj2823)
左偏樹(可合並堆).

後綴樹(非常有用的數據結構,也是賽區考題的熱點).(poj3415,poj3294)
四.搜索

較麻煩的搜索題目訓練(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)

廣搜的狀態優化:利用M進制數存儲狀態、轉化為串用hash表判重、按位壓縮存儲狀態、雙向廣搜、A*演算法. (poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)

深搜的優化:盡量用位運算、一定要加剪枝、函數參數盡可能少、層數不易過大、可以考慮雙向搜索或者是輪換搜索、IDA*演算法. (poj3131,poj2870,poj2286)

五.動態規劃

需要用數據結構優化的動態規劃.(poj2754,poj3378,poj3017)
四邊形不等式理論.

較難的狀態DP(poj3133)

六.數學

組合數學.
1.MoBius反演(poj2888,poj2154)
2.偏序關系理論.
博奕論.
1.極大極小過程(poj3317,poj1085)
2.Nim問題.
七.計算幾何學.

半平面求交(poj3384,poj2540)

可視圖的建立(poj2966)

點集最小圓覆蓋.

對踵點(poj2079)

❽ 程序員如何學好演算法

一.基本演算法:

枚舉. (poj1753,poj2965)

貪心(poj1328,poj2109,poj2586)

遞歸和分治法.

遞推.

構造法.(poj3295)

模擬法.(poj1068,poj2632,poj1573,poj2993,poj2996)

二.圖演算法:

圖的深度優先遍歷和廣度優先遍歷.

最短路徑演算法(dijkstra,bellman-ford,floyd,heap+dijkstra)
(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)
最小生成樹演算法(prim,kruskal)
(poj1789,poj2485,poj1258,poj3026)
拓撲排序 (poj1094)

二分圖的最大匹配 (匈牙利演算法) (poj3041,poj3020)

最大流的增廣路演算法(KM演算法). (poj1459,poj3436)

三.數據結構.

串 (poj1035,poj3080,poj1936)

排序(快排、歸並排(與逆序數有關)、堆排) (poj2388,poj2299)

簡單並查集的應用.

哈希表和二分查找等高效查找法(數的Hash,串的Hash)
(poj3349,poj3274,POJ2151,poj1840,poj2002,poj2503)
哈夫曼樹(poj3253)



trie樹(靜態建樹、動態建樹) (poj2513)

四.簡單搜索

深度優先搜索 (poj2488,poj3083,poj3009,poj1321,poj2251)

廣度優先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)

簡單搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)

五.動態規劃

背包問題. (poj1837,poj1276)

型如下表的簡單DP(可參考lrj的書 page149):
E[j]=opt{D+w(i,j)} (poj3267,poj1836,poj1260,poj2533)
E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1]+zij} (最長公共子序列) (poj3176,poj1080,poj1159)
C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最優二分檢索樹問題)
六.數學

組合數學:
1.加法原理和乘法原理.
2.排列組合.
3.遞推關系.
(POJ3252,poj1850,poj1019,poj1942)
數論.
1.素數與整除問題
2.進制位.
3.同餘模運算.
(poj2635, poj3292,poj1845,poj2115)
計算方法.
1.二分法求解單調函數相關知識.(poj3273,poj3258,poj1905,poj3122)
七.計算幾何學.

幾何公式.

叉積和點積的運用(如線段相交的判定,點到線段的距離等). (poj2031,poj1039)

多邊型的簡單演算法(求面積)和相關判定(點在多邊型內,多邊型是否相交)
(poj1408,poj1584)
凸包. (poj2187,poj1113)

中級(校賽壓軸及省賽中等難度):
一.基本演算法:

C++的標准模版庫的應用. (poj3096,poj3007)

較為復雜的模擬題的訓練(poj3393,poj1472,poj3371,poj1027,poj2706)

二.圖演算法:

差分約束系統的建立和求解. (poj1201,poj2983)

最小費用最大流(poj2516,poj2516,poj2195)

雙連通分量(poj2942)

強連通分支及其縮點.(poj2186)

圖的割邊和割點(poj3352)

最小割模型、網路流規約(poj3308)

三.數據結構.

線段樹. (poj2528,poj2828,poj2777,poj2886,poj2750)

靜態二叉檢索樹. (poj2482,poj2352)

樹狀樹組(poj1195,poj3321)

RMQ. (poj3264,poj3368)

並查集的高級應用. (poj1703,2492)

KMP演算法. (poj1961,poj2406)

四.搜索

最優化剪枝和可行性剪枝

搜索的技巧和優化 (poj3411,poj1724)

記憶化搜索(poj3373,poj1691)

五.動態規劃

較為復雜的動態規劃(如動態規劃解特別的旅行商TSP問題等)
(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)
記錄狀態的動態規劃. (POJ3254,poj2411,poj1185)

樹型動態規劃(poj2057,poj1947,poj2486,poj3140)

六.數學

組合數學:
1.容斥原理.
2.抽屜原理.
3.置換群與Polya定理(poj1286,poj2409,poj3270,poj1026).
4.遞推關系和母函數.
數學.
1.高斯消元法(poj2947,poj1487, poj2065,poj1166,poj1222)
2.概率問題. (poj3071,poj3440)
3.GCD、擴展的歐幾里德(中國剩餘定理) (poj3101)
計算方法.
1.0/1分數規劃. (poj2976)
2.三分法求解單峰(單谷)的極值.
3.矩陣法(poj3150,poj3422,poj3070)
4.迭代逼近(poj3301)
隨機化演算法(poj3318,poj2454)
雜題(poj1870,poj3296,poj3286,poj1095)
七.計算幾何學.

坐標離散化.

掃描線演算法(例如求矩形的面積和周長並,常和線段樹或堆一起使用)
(poj1765,poj1177,poj1151,poj3277,poj2280,poj3004)
多邊形的內核(半平面交)(poj3130,poj3335)

幾何工具的綜合應用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)

高級(regional中等難度):
一.基本演算法要求:

代碼快速寫成,精簡但不失風格

(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)

保證正確性和高效性. poj3434

二.圖演算法:

度限制最小生成樹和第K最短路. (poj1639)

最短路,最小生成樹,二分圖,最大流問題的相關理論(主要是模型建立和求解)
(poj3155, poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446
最優比率生成樹. (poj2728)

最小樹形圖(poj3164)

次小生成樹.

無向圖、有向圖的最小環

三.數據結構.

trie圖的建立和應用. (poj2778)

LCA和RMQ問題(LCA(最近公共祖先問題) 有離線演算法(並查集+dfs) 和 在線演算法(RMQ+dfs)).(poj1330)
雙端隊列和它的應用(維護一個單調的隊列,常常在動態規劃中起到優化狀態轉移的目的). (poj2823)
左偏樹(可合並堆).

後綴樹(非常有用的數據結構,也是賽區考題的熱點).(poj3415,poj3294)
四.搜索

較麻煩的搜索題目訓練(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)

廣搜的狀態優化:利用M進制數存儲狀態、轉化為串用hash表判重、按位壓縮存儲狀態、雙向廣搜、A*演算法. (poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)

深搜的優化:盡量用位運算、一定要加剪枝、函數參數盡可能少、層數不易過大、可以考慮雙向搜索或者是輪換搜索、IDA*演算法. (poj3131,poj2870,poj2286)

五.動態規劃

需要用數據結構優化的動態規劃.(poj2754,poj3378,poj3017)
四邊形不等式理論.

較難的狀態DP(poj3133)

六.數學

組合數學.
1.MoBius反演(poj2888,poj2154)
2.偏序關系理論.
博奕論.
1.極大極小過程(poj3317,poj1085)
2.Nim問題.
七.計算幾何學.

半平面求交(poj3384,poj2540)

可視圖的建立(poj2966)

點集最小圓覆蓋.

對踵點(poj2079)

❾ 搞編程的我是個演算法渣,怎麼樣能很快的提升演算法水平有什麼必要的或者非常基礎的演算法需要掌握

演算法的實現需要你對數據結構有充分的理解,我個人覺得數據結構是演算法的基礎,至少我是先熟悉數據結構再弄演算法的,這樣接受起來比較快。所以建議你
1:先花些時間掌握數據結構知識,比如數據結構基本類型;線性表、樹、圖、集合的存儲表示以及他們的應用,而要想熟練運用這些線性表、樹、圖、集合,那麼又必須要非常熟練棧和隊列,因為棧和隊列是必不可少的,如果你非常熟練運用棧和隊列,那麼你肯定能輕松搞定牽涉到線性表、樹等這些應用的。
2:掌握基本的查找演算法和排序演算法;因為有了上述數據結構的鋪墊,也較容易接受查找和排序演算法在計算機內部的組織形式,對於運用計算機思想思考問題有很大的幫助。
3:學習常用的演算法思想,如分治、貪心、動態規劃、回溯等等。學習之後自己動手找一些題目敲敲代碼,剛開始可以按照答案敲,慢慢要丟開答案自己來組織思路了。
4:要熟悉分析演算法的復雜度,因為接著要開始思考代價問題了,包括時間和空間的開銷。
其實用誰的書都無所謂,只要內容齊全了,而你自己閱讀起來接受得更好就用誰的。如果還有時間,推薦你看看朱東生趙建利等的《新編數據結構演算法 考研指導》(當時我考研用來輔助看的,裡面講解的遞歸與非遞歸之間的轉換非常好)。
5:如果有興趣可以看看《編程珠璣》和《編程之美》,有些企業招聘時會從中挑個別題目出題。
總之,我覺得數據結構是基礎,演算法是靈魂。多思考,多運用就能熟能生巧了。工科類的不多動動手那些知識是很容易生疏的。
以上觀點僅供參考,純屬個人觀點。

❿ 求計算演算法的復雜度 (Python寫的邏輯)

(a) 演算法復雜度為O(n),因為只有一個while循環,且i<n,所以復雜度是線性級,僅跟n有關
(b) 演算法復雜度為O(n²),實際上演算法復雜度為nxn/2 = n²/2,因為有for循環的嵌套
(c) 演算法復雜度為O(n),因為只有while循環,盡管裡面i=ix2,但是這是常數級操作
(d) 演算法復雜度為O(log i),這是對數級操作,每次i除以2,所以是log(i)base(2)
(e) 演算法復雜度為O(n log n)
(f) 演算法復雜度為O(2^i),這是一個遞歸演算法,為指數級
(g) 演算法復雜度為O(n 2^n),這是一個交換數據的演算法,是一個遞歸+一個for 循環

閱讀全文

與程序員的復雜演算法相關的資料

熱點內容
進入組策略的命令 瀏覽:137
python數據結構和內存 瀏覽:25
python軟體功能簡介 瀏覽:784
外國程序員一般多少歲退休 瀏覽:917
怎麼看linux和時間伺服器 瀏覽:680
程序員搞笑花名 瀏覽:501
dota2怎麼設置國服伺服器地址 瀏覽:212
單片機高電平驅動 瀏覽:115
ios多選文件夾 瀏覽:909
加強行車調度命令管理 瀏覽:243
伺服器已禁用什麼意思 瀏覽:150
部隊命令回復 瀏覽:755
神奇寶貝伺服器地圖怎麼設置 瀏覽:382
加密演算法輸出固定長度 瀏覽:862
程序員去重慶還是武漢 瀏覽:121
伺服器如何撤銷網頁登錄限制 瀏覽:980
微信公眾平台php開發視頻教程 瀏覽:628
怎麼看蘋果授權綁定的app 瀏覽:255
壓縮機單級壓縮比 瀏覽:380
linux測試php 瀏覽:971