『壹』 程序員需要怎樣的數學基礎
離散數學對程序員來說非常重要,還有組合數學、線性代數、概率論、數論等等,即使你將來不做研究,這些基礎知識也能極大地提高你的水平。計算機科學對離散數學的要求很高,建議你先學習前面提到的這些課程,然後學習計算機演算法和數據結構,再配合到網上的在線題庫做題,過程很艱辛,但是對你的幫助會很大。
推薦書目:
《具體數學》(先學完前面的數學課程,在水平有一定進步以後再看)
《演算法導論》(應該人手一本的好書)
簡單來說,學數學的目的,一方面是活躍你的思維;另一方面是為了深入學習演算法打基礎,設想一下,同樣的問題,普通人的程序要幾十分鍾甚至幾小時幾天才能解決出來,甚至根本無法解決,而你精心設計的程序卻能在1秒內解決出來,這就是數學的魅力、演算法的魅力。
其實,一切取決於你是否想做一個高級程序員。如果你做體力活(其實一般編程別人都認為是體力活),那你可以不學,因為你用不到,但是,你要是做技術上的創新,做個很強的程序員,沒有數學的支持,很難。
你既然學習了C,c++,你也知道演算法的重要性,同樣一個問題,我用13行程序解決了,我的同學居然用了33行,因為他不懂的用數學。你要達到什麼高等,取決於你的數學修養。當然,要做一個普通的程序員就不用學習了。要挑戰自己,做個好的,優秀的,學習數學吧!
『貳』 QQ秀里的魅力值是什麼個演算法為什麼這幾天支線下降
魅力直是鮮花工廠裡面的鮮花決定的,送給你花的人越多你的魅力直就會增加,鮮花是有花期的,一般免費的玫瑰就是15天,時間一到魅力直就會消失
『叄』 遞歸演算法有何特點
遞歸4—遞歸的弱點
之所以沒有把這段歸為演算法的討論,因為這里討論的不在是演算法,而只是討論一下濫用遞歸的不好的一面。
遞歸的用法似乎是很容易的,但是遞歸還是有她的致命弱點,那就是如果運用不恰當,濫用遞歸,程序的運行效率會非常的低,低到什麼程度,低到出乎你的想像!當然,平時的小程序是看不出什麼的,但是一旦在大項目里濫用遞歸,效率問題將引起程序的實用性的大大降低!
例子:求1到200的自然數的和。
第一種做法:
#include <stdio.h>
void main()
{
int i;
int sum=0;
for(i=1;i<=200;i++)
{
sum+=i;
}
printf("%d\n",sum);
}
該代碼中使用變數2個,計算200次。再看下個代碼:
#include <stdio.h>
int add(int i)
{
if(i==1)
{
return i;
}
else
{
return i+add(i-1);
}
}
void main()
{
int i;
int sum=0;
sum=add(200);
printf("%d\n",sum);
}
但看add()函數,每次調用要聲明一個變數,每次調用要計算一次,所以應該是200個變數,200次計算,對比一下想想,如果程序要求遞歸次數非常多的時候,而且類似與這種情況,我們還能用遞歸去做嗎?這個時候寧願麻煩點去考慮其他辦法,也要嘗試擺脫遞歸的干擾。
21:21 | 添加評論 | 固定鏈接 | 引用通告 (0) | 記錄它 | 計算機與 Internet
程序演算法5—遞歸3—遞歸的再次挖掘
遞歸的魅力就在於遞歸的代碼,寫出來實在是太簡練了,而且能解決很多看起來似乎有規律但是又不是一下子能表達清楚的一些問題。思路清晰了,遞歸一寫出來問題立即就解決了,給人一重感覺,遞歸這么好用。我們在此再更深的挖掘一下遞歸的用法。
之前再強調一點,也許有人會問,你前邊的例子用遞歸似乎是更麻煩了。是,是麻煩了,因為為了方便理解,只能舉一些容易理解的例子,一般等實際應用遞歸的時候,遠遠不是這種狀態。
好了我們現在看一個數字的序列;有一組數的集合{1,2,4,7,11,16,22,29,37,46,56……}我故意多給幾項,一般是只給前4項讓你找規律的。序列給了,要求是求前50項的和。規律?有?還是沒有?一看就象有,但是又看不出來,我多給了幾項,應該很快看出來了,哦,原來每相鄰的兩項的差是個自然數排列,2-1=1,4-2=2,7-4=3,11-7=4,16-11=5……
好了,把規律找出來了,一開始可能覺得沒頭緒,沒問題,咱們把這個序列存放到一個數組總可以吧!那我們就聲明一個數組,存放前50個數據,一個一個相加總可以了。於是有了下邊的寫法:
#include <stdio.h>
void main()
{
int i,a[50],sum=0;
a[0]=1;
for(i=1;i<50;i++)
{
a[i]=a[i-1]+i;
}
for(i=0;i<50;i++)
{
sum+=a[i];
}
printf("%d\n",sum);
}
好了,代碼運行一下,結果出來了,正確不正確呢?自己測試吧,把50項改成1、2、3、4、5……項,試試前多少項是不是正確,雖然這不是正確的測試方法,但是的確是常用的測試方法。
等到這個代碼已經完全理解了,完全明白了正個計算過程,我們就應該對這段代碼進行改寫優化了,畢竟這個代碼還是不值得用一個數組的,那麼我們嘗試著只用變數去做一下:
#include <stdio.h>
void main()
{
int i;
int number=1;
int sum=0;
for(i=0;i<50;i++)
{
number+=i;
sum+=number;
}
printf("%d\n",sum);
}
不知道我這樣寫是不是跨度大了點,但是我不準備詳細解釋了,很多東西需要你去認真分析的,所以很多東西如果不懂,自己想清楚比別人解釋的效果會更好,因為別人講只能讓你理解,如果你自己去想,你就在理解的同時學會了思考。
這個代碼寫出來,不要繼續看下去,先自己嘗試著把這個題目用遞歸做一下看看自己能不能寫出來,當然,遞歸並不是那麼輕松就能使用的,有時候也是需要去細心設計的。如果做出來了,對比一下下邊的代碼,如果沒有寫出來,建議認真分析後邊的代碼,然後最好是能完全掌握,能自己隨時把這行代碼寫出來:
#include <stdio.h>
int add(int n,int num,int i)
{
num+=i;
if(i>=n-1)
{
return num;
}
else
{
return num+add(n,num,i+1);
}
}
void main()
{
int sum;
sum=add(50,1,0); /*50表示前50象項*/
printf("%d\n",sum);
}
當然這個代碼中的n只是一個參考變數,如果把if(i>=n-1)中的n該成50,那麼就不需要這個n了,函數兩個參數就可以了,這樣寫是為了修改方便。
20:28 | 添加評論 | 固定鏈接 | 引用通告 (0) | 記錄它 | 計算機與 Internet
程序演算法4—遞歸2—遞歸的魅力
兩天沒有再寫下去,因為畢竟有時候會有點心情問題,有時候覺得心情不好,一下子什麼東西都想不起來了,很多時候寫一些東西是需要狀態的,一旦狀態有了,想的東西才能順利的寫出來,雖然有些東西寫出來在別人看來很垃圾,但是起碼自己覺得還是相當滿意的,我寫這個本來就沒有多少技術含量,只是想給初學程序的人一些指引,加快他們對程序的領悟!
好了,言歸正傳,繼續上次遞歸的討論,看看遞歸的魅力所在。
有這樣一個問題,說一個猴子和一堆蘋果,猴子一天吃一半,然後再吃一個,10天後剩下一個了,也就是說吃了10次,剩下1個了。問原來一共有多少蘋果。
當然我們的目的不是求出蘋果的數量,而是尋求一種解決問題的方法,這個問題一出來,通常對程序掌握深度不一樣的朋友對這個題會有不同的認識,首先介紹一種解決方法,這種人腦袋還是比較聰明的,思路非常的明確,也有可能語言工具掌握的也不錯,代碼寫出來非常准確,先看一下代碼再做評價吧:
#include <stdio.h>
void main()
{
int day=10;
int apple;
int i,j;
for(i=1;;i++)
{
apple=i;
for(j=0;j<day;j++)
{
if(apple%2==0&&apple>0)
{
apple/=2;
apple--;
}
else
{
break;
}
}
if(j==day&&apple==1)
{
printf("%d\n",i);
return;
}
}
}
程序的大概思路很明確,簡單介紹一下,這種寫法就是從一個蘋果開始算起,for(i=1;;i++)的作用就是改變蘋果的數量,如果1個符合條件,那就試試2個,然後3個、4個一直到適合為止,里邊的for循環就是把每一次取得的蘋果的數目進行計算,如果每次都能順利的被2整除(也就是說每次都能保證猴子能正好吃一半),然後再減一一直到最後,如果最後蘋果剩下是一個而且天數正好是10天,那麼就輸出一下蘋果的數目,整個程序退出,如果看不明白的沒關系,這個寫法非常的不適用,我們叫寫出這種演算法的人傻X,雖然這種人腦袋也挺聰明,能寫出一些新鮮的寫法,但是又臟又臭,代碼既不簡練又不高效。
所以說,有時候有些人以為自己學的很好了,自己所做的一切都是最好的,這種想法是不正確的,也許有些初學者沒有什麼經驗寫出來的代碼卻更讓人容易明白點,那麼也是先看看代碼:
#include <stdio.h>
void main()
{
int day[11];
int i;
day[0]=1;
for(i=1;i<11;i++)
{
day[i]=(day[i-1]+1)*2;
}
printf("%d\n",day[10]);
}
代碼不長,而且也恰當的應用了題目中的規律,不是說要吃一半然後再吃一個嗎?那我用數組來存放每天蘋果的數量,用day[0]表示最後一天的蘋果數量,那就是剩下的一個,然後就是找規律了,什麼規律?就是如果猴子不多吃一個的話,那就是正好吃了一半,也就是說猴子當天吃了之後剩餘的蘋果的數目加1個然後再乘以2就是前一天的數目了,這樣一想這個題目就簡單的多了,於是這個題用數組就輕松的做出來了。
那麼這個代碼究竟是不是已經很好了呢,我們注意到,這里邊每個數組元素只用了一次並沒有被重復使用,再這種情況下我們是不是可以用一種方法代替數組呢?於是就有了更優化的寫法,這個寫法似乎已經是相當簡練了:
#include <stdio.h>
void main()
{
int apple=1;
int i;
for(i=0;i<10;i++)
{
apple=(apple+1)*2;
}
printf("%d\n",apple);
}
代碼寫到這里已經把問題完全抽象化了,所以我們就應該站在數學的角度去分析了。也許我們就應該結束了討論,但是偏偏這個時候,又來了遞歸,悄悄的通過美麗的調用顯示了一下她的魅力:
#include <stdio.h>
int apple(int i)
{
if(i==0)
{
return 1;
}
else
{
return (apple(i-1)+1)*2;
}
}
void main()
{
int i;
i=apple(10);
printf("%d\n",i);
}
原理都還是一樣的,但是寫出來的格式已經完全變掉了,沒有了for循環。假想一個復雜的問題遠比這個問題復雜,而且沒有固定循環次數,那麼我們再使用循環雖然也能解決問題,但是可能面臨循環難以設計、控制等問題,這個時候用遞歸可能就會讓問題變的非常的清晰。
另外說一點,一般我這里的代碼,並不是從最差到最好的,基本排列是從最差到最合適的代碼(當然是本人認為最合適的,也許還有更好的,本人能力所限了),然後最後給出一種比較違反常規的代碼,一般是不贊成用最後一種代碼的,當然有時候最後一種代碼也許是最好的選擇,看情況吧!
20:25 | 添加評論 | 固定鏈接 | 引用通告 (0) | 記錄它 | 計算機與 Internet
10月15日
程序演算法3—遞歸1—遞歸小顯威力
現在用C語言實現一個字元串的倒序輸出,當然,方法也是很多的,但是如果程序中能有相對優化的方法或者簡單明了易讀的方法,那對你自己或者別人都是一種幸福。
第一種寫法,這類寫法既浪費內存又不實用,一般是剛學程序的才這樣做,程序的結構很簡單,利用的是數組:
#include <stdio.h>
void main()
{
char c[2000];
int i,length=0;
for(i=0;i<2000;i++)
{
scanf("%c",&c[i]);
if(c[i]=='\n')
{
break;
}
else
{
length++;
}
}
for(i=length;i>0;i--)
{
printf("%c",c[i-1]);
}
printf("\n");
}
這段代碼中的數組,聲明大了浪費內存空間,聲明小了又怕不夠,所以寫這種代碼的人一般寫完之後會祈禱,祈禱測試的人不要輸入的太多,太多就不能完全顯示了!
與其這么提心吊膽,於是又有人想出了第二種方法,終於解決了一些問題,而且完全實現了程序的實際要求,於是,這種人經過一番苦想,覺得問題終於可以解決了,這種方法看起來是一種很不錯的方法。
#include <stdio.h>
#include <malloc.h>
void main()
{
int i;
char *c;
c=(char *)malloc(1*sizeof(char));
for(i=0;;i++)
{
*(c+i)=getchar();
if(*(c+i)=='\n')
{
*(c+i)='\0';
break;
}
else
c=(char *)realloc(c,(i+2)*sizeof(char));
}
for(--i;i>=0;i--)
{
putchar(*(c+i));
}
printf("\n");
free(c);
}
怎麼樣?不錯,准確的應用內存,幾乎沒有浪費什麼空間,這種方法也體現了一下指針的強大功能,寫這個程序雖然不敢說這個人已經掌握了指針的應用,但是起碼可以說他已經會用指針了。代碼寫出來,看起來已經有點美感。
但是也有一些人還是比較喜歡動腦筋的,經過一番思考,終於想出了第三種比較容易寫的方法,也許有寫初學者可能覺得有些難度,但是事實上這個東西一點都不難,如果稍微有點程序功底之後再看這段代碼,應該是相當輕松!
#include <stdio.h>
void run()
{
char c;
c=getchar();
if(c!='\n')
{
run();
}
else
{
return;
}
putchar(c);
}
void main()
{
run();
printf("\n");
}
寫出的代碼讓人眼前一亮,哇!原來遞歸功能簡單而又好用,那我們為什麼不好好利用呢?但是遞歸也不一定就是最好的選擇,因為有時候雖然遞歸用起來很方便,但是效率卻不高,以後的討論中還會詳細說明。
『肆』 急呀!!請問哪位高手知道用手指計算加減乘除法的呀
如果你是因為看到下面這則新聞才問的,那沒辦法,不能幫您省個買書的錢了
中學老師掐手指計算百萬以下運算
2006年04月03日 15:23:38 杭州網
「我們的兩只手,也是一個完美的計算器,一般用它可能進行六位數以內的加減乘除、平方、開平方六種計算。其運算速度,加減速度可與電子計算機相媲美,乘除比珠算還要快,平方、開平方比筆算快得多。」這種堪稱神奇的演算法便是榆中四中一名中學教師羅彥頻歷經十年發明的「手指速演算法」。
3月30日,當中央電視台《想挑戰嗎?》
欄目從網上看到此消息後,向這名中學教師發出了真誠的邀請,以期讓全國人民目睹這種神奇演算法的魅力。昨日,記者來到榆中羅彥頻的家中全程見證了這種國內首創、世界獨一的「手指速演算法」。
100萬數字以下隨便出題
中午,當清瘦的羅彥頻出現在記者面前時,他用05年新出的一本書作為開場白介紹了自己。在一本名為《手指速演算法》的書中,記者對羅彥頻有了初步的了解。無需藉助其他計算工具,只需用兩只手,就能快速完美地完成加減乘除、平方、開平方等運算。同時,羅彥頻信心十足地告訴記者,只要是100萬以下的數字,記者可以隨便說出一組數字,他都能快速且正確無誤地說出答案。
為驗證此話的真實性,記者當場寫下79856+97656,只見羅彥頻伸出雙手,用拇指、食指和無名指掐掐算算,3秒鍾後說出了答案:177512。而此時,記者才剛剛在計算器上將數字輸入完畢。此後,記者又出了一道帶小數點的乘法,5784.7*94,不到30秒羅彥頻抬起頭,面帶微笑地回答:等於543761.8。而記者在紙上演算時仍然慢了他一步。更令人稱奇的是,「手指速演算法」中的加減乘法等已被羅彥頻列到簡單的行列,而他最在行的卻是開平方。對0.034226進行開平方時,羅彥頻僅用了四十秒便正確地說出了答案。在進行一番驗證後,羅彥頻以絕對的實力證明,他的「手指速演算法」絕不是空穴來風,而是一門快速科學、簡單實用的計算方法。
央視關注「手指速演算法」
為將自己發明創造的「手指速演算法」在全國推廣,2005年3月,羅彥頻歷經十年自編的《手指速演算法》一書終於面世。該書一經出版,被甘肅省政法學院一名愛好速算的大學生梁權購得。書上的內容深深吸引了梁權,兩人由此相識。在梁權的幫助下,在前羅彥頻「手指速算」的內容頻頻出現在各大網站。也就是這個機會,有幸讓羅彥頻結識了全國各地的朋友。2005年7月,中央電視台《想挑戰嗎?》欄目從網上發現羅彥頻的手指速算消息後,對此進行了極大的關注,並希望羅彥頻能親自到現場錄制節日,為全國觀眾演繹手指速算的全過程,展示一個新奇的速算領域。
自己發明的速算方法得到中央電視台的關注,羅彥頻的喜悅之情溢於言表。他高興地告訴記者,3月30日,中央電視台的工作人員還督促他盡快整理錄像資料寄到總部。並清楚地告訴他,等待的時間不會太長。
更讓羅彥頻受益匪淺的是,他的「手指速演算法」也讓他結識了全國各地的朋友。幾個月來,全國200多人向他打電話或發簡訊咨詢手指速算的學習方法。在羅彥頻的手機上,一名黑龍江的男子說,「昨晚我激動得徹夜難眠,15年來,我在尋求探索手指教學,今天終於如願。是發達的高科技讓我們相識,讓我們攜手共進!同時該男子還誠懇地表示,6月他將抵蘭拜羅彥頻為師,希望推廣速演算法。
「速算」問世受侄女啟發
當今社會,許多人已習慣了藉助於計算工具進行運算。而羅彥頻是怎麼匠心獨運地想到發明創造「手指速演算法」?羅彥頻笑著說,其實很簡單。十年前,當我看到上小學一年級的侄女扳著手指頭算數字時,突然萌發了是否發明一種快速簡單的運算方法。在此想法的啟發下,羅彥頻不斷地思考、嘗試,構思了手指速算的框架。即通過各手指的展、伸、捏、屈等動作完成運算。在解釋這種速演算法的實用性時,羅彥頻說,手指速算人人都能學,人人都能用。對真心想學的人來說,十幾分鍾就能學會,但需長期堅持練習,熟練後人人都能成為速算專家。一旦學會,將會終生受益,既能算數,又能巧手益智、健腦強身、可謂一舉多得。
從發明到熟練運用,羅彥頻本人又用了多長時間超過計算機、計算器的運算速度呢?當記者提出這個問題時,羅彥頻笑了,「許多給我發簡訊的人都問過相同的問題」。盡管我發明了「手指速演算法」,但我的成長過程也是通過長期堅持不懈的練習才得以成功。因此,可以說要想成功能是沒有捷徑可走的。
來源:蘭州晚報
最後的建議還是:買本書,支持羅彥頻老師!!!
再者,如果這里這么小的篇幅就能告訴你怎樣用手指計算加減乘除法,人家也不用出上一本書啊,!!出幾頁紙然後賣報一樣地四處發就行啦~~
如果這里這么小的篇幅就能告訴你怎樣用手指計算加減乘除法,別人都會來網路知道學那東西,書就一本都難賣了,羅彥頻也一定想過這個問題,可書還是照出照賣,所以我們可以確定,這個問題在這兒沒得說清!!!
『伍』 X分之3.6等於3分之二節比例
排序演算法第一篇-排序演算法介紹
在面試中,現在無論大小公司都會有演算法的。其中排序演算法也是一種很常見的面試題。比如冒泡,快排等。這些,排序演算法自己看了一次又一次,可是過一段時間,又忘掉了。所以,這次就把演算法是怎麼推導出來的,詳細記錄下來。看看這次多久還會忘記。
本文主要介紹排序演算法的分類、時間復雜度、空間復雜。為了後面的學習做准備的。
通過本文學習,將收獲到:排序演算法分幾類?什麼是演算法的時間復雜度?是怎麼算出來的?什麼是演算法的空間復雜度?常見的時間復雜度比較。
如果這些您都已經知道了,可以不用耽誤時間看了。
約定:
文中的n2表示的是n的2次方(n²),n^2也是表示n的2次方;
n3表示的是n的3次方;
n^k表示的是n的k次方;
long2n表示的是以2為底的對數。
本文出自:凱哥java(微信:kaigejava)學習Java版數據結構與演算法筆記。
一:介紹
排序又稱排序演算法(Sort Algorithm),排序是將一組數據,依據指定的順序進行排序的過程。
二:分類
排序的分類分為兩大類
2.1:內部排序
內部排序是指將需要處理的所有數據一次性都載入到內存中進行排序的。
如:冒泡、快排等這些演算法都是內部排序的
2.2:外部排序
數據量過大,無法全部載入到內存中,需要藉助於外部存儲進行排序的。
如:資料庫中數據8個G,內存只有4個G的這種。
2.3:參加分類如下圖:
三:演算法的時間復雜度
3.1:分類
衡量一個程序(演算法)執行時間有兩種方法
3.1.1:事後統計的方法
所謂的事後統計方法,顧名思義,就是程序(演算法)已經寫完了,運行後得到的結果。
這種方法雖然是可行的,但是有兩個問題:
①:要想對設計的演算法運行的性能進行評估,需要實際運行該程序(浪費時間);
②:運行所得的時間統計嚴重依賴於機器的硬體、軟體等環境因為。
這種方法有個嚴苛的要求:要在同一台機器在相同狀態(軟硬體)下運行,才能比較哪個演算法更快。
3.1.2:事前估算的方法
通過分析某個演算法的時間復雜度來判斷哪個演算法更優。
3.2:時間頻度
概念:一個演算法花費的時間與演算法中語句執行的次數成正比。哪個演算法中語句執行次數多,那麼這個演算法所花費的時間就多(這不廢話嗎)。
一個演算法中語句執行次數稱為語句頻度或時間頻度。記為:T(n).
(復雜的概念是,時間頻度:一個演算法執行所消耗的時間,從理論上是 不能算出來的,想要具體數值,必須要將程序上機運行測試才能知道。但是我們不可能也沒必要對每個演算法都上機進行測試的,只需要知道哪個演算法花費的時間多,哪個演算法花費的時間少就可以了。並且一個演算法花費的時間與演算法中語句執行的次數成正比的,哪個演算法中語句執行次數多,那麼這個程序花費的時間就多。一個演算法中的語句執行次數稱為語句頻度或者時間頻度,即為:T(n))
例如:我們知道的技術從1到100所有數字的和。這個就有兩種演算法。分別如下:
①:使用for循環,從1到100循環出來,然後累加出來。代碼如下:
根據上面概念(注意對概念的理解,total和end這兩行相對於for循環來說,可以忽略。後面我們還會詳細講解還會忽略哪些),我們來看下這個演算法的時間頻度是多少呢?
在for循環中,實際需要執行101次(+1的原因是因為,在for循環的時候,需要做最後一次判斷,才能推出。因此n個數的計算一共是n+1次操作)。所以其時間頻度就是:T(n)=n+1;
我們再來看看第二種演算法:
是不是很簡單,只要一行代碼就執行完成了。所以第二種演算法的T(n)=1了。是不是很快呢?
時間頻度是不是一眼就看出來了?是不是不用在代碼運行下來比較運行時間了?
(ps:從上面簡單地從1到100求和演算法中,我們是不是感受到演算法的魅力了?感受到編程之美了?)
3.3:時間復雜度
在上面3.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))為演算法的漸進的時間復雜度。簡稱時間復雜度。這就是大O法。
在計算時間復雜度的時候,我們會忽略以下幾個數據值
3.3.1:忽略常數項
比如上面,我們計算1到100的第一種演算法中,有兩行int total=0;和 int end = 100;這兩行代碼,這個數值是2,我們一般計算時間復雜度的時候,會忽略這個常數項的。為什麼呢?請看下面四個函數,隨著n的增大而增大運行時間。
T(n) = 2n+20
T(n) = 2*n
T(n)=3n+10
T(n)=3*n
請看下圖隨著n的增大所呈現的規律:
我們來看看,把這些數據使用折線圖展示:
圖例說明:上面兩個是3*n及3n+10的,下面兩個是2n及2n+10的
從上面兩個圖表中我們可以得到以下結論:
①:2n+20和2*n隨著n的增加,執行曲線無限接近(折線圖中下面兩個),常量值20可以忽略了
②:3n+10和3*n隨著n的增加,執行曲線無限接近(折線圖中上面兩個),常量值10可以忽略了
所以,綜上所述,在計算程序(演算法)時間復雜度的時候,常量值是可以忽略的
3.3.2:忽略低次項
請看下面四個函數,隨著n的增大又會呈現什麼規律嗎?
T(n)=2n^2+3n+10
T(n)=2n^2
T(n)=n^2+5n+20
T(n)=n^2
說明:n^2表示n的2次方
我們來看看隨著n的增加,運行所消耗的時間。如下圖:
把上面數據,用折線圖表示,如下圖:
圖例說明:上面兩個是2n^2及2n^2+3n+10,下面兩個是n^2及 n^2+5n+20
從上面兩個圖中我們可以得到如下結論:
①:2n^2+3n+10和2n^2隨著n的增大,執行曲線無限接近,可以忽略低次項及常量項:3n+10
②:n^2+5n+20和n^2隨著n的增大,執行曲線無限接近,可以忽略低次項及常量項:5n+20
綜上所述,我們可以得到結論:在計算程序(演算法)時間復雜度的時候,低次項(3n=3*n^1比n^2項數少)是可以忽略的
3.3.3:忽略系數
我們再來看看下面四個函數,看看它們隨著n的增大呈現出什麼樣的規律
T(n)=3n^2+2n
T(n)=5n^2+7n
T(n)=n^3+5n
T(n)=6n^3+4n
隨著n的增加,運行時間所消耗耗時如下圖:
折線圖如下:
從上圖可以得到如下:
①:隨著n值變大,5n^2+7n和3n^2+2n,執行曲線重合,說明這種情況下,系數5和3可以忽略;
②:n^3+5n和6n^3+4n,執行曲線分離,說明多少次方是關鍵
3.3.4:總結:
計算時間復雜度的時候忽略常數項、忽略低次項、忽略系數
T(n)不同,但時間復雜度可能相同。
如:T(n)=n2+7n+6與T(n)=3n^2+2n+2它們的T(n)不同,但時間復雜相同,都為O(n^2).
計算時間復雜度的方法用常數1代替運行時間中的所有加法常數T(n)=n^2+7n+6 =>T(n)=n^2+7n+1修改後的運行次數函數中,只保留最高階項T(n)=n^2+7n+1 => T(n)=n^2去除最高階項的系數T(n)=n^2 =>T(n)=n^2 => O(n^2)
3.4:常見的時間復雜度
常數階O(1)
對數階O(log2n)
線性階O(n)
線性對數階O(nlog2n)
平方階O(n^2)
立方階O(n^3)
K次方階(n^k)
指數階O(2^n)
各個時間復雜度復雜度折線圖如下圖:
總結:
常見演算法時間復雜度由小到大依次為:
O(1)
從上圖折線圖中,我們可以看出,程序(演算法)盡可能的避免使用指數階段的演算法。
3.5:常見演算法時間復雜度舉例
3.5.1:常數階O(1)
無論代碼執行多少行,只要是沒有循環等復雜結構,那這個代碼的時間復雜度就是O(1)
(計算時間復雜度的時候,忽略常數項)
代碼demo:
上述代碼在執行的時候,消耗的時間並不是隨著某個變數的增長而增長,那麼無論這類代碼有多長,即使有有幾萬幾十萬行,都是可以用O(1)來表示它的時間復雜度。
3.5.2:對數階O(log2n)
代碼敬上:
說明:
在while循環裡面,每次都是將i*2的。n的值是固定的,所以在i乘完之後,i距離n就越來越近了。假設循環x次之後,i就大於n了,此時這個循環就退出了。也就是說2的x次方等於n了。那麼x=log2n。也就是說當循環了log2n次以後,代碼就結束了。因此這個代碼的時間復雜度就是
O(log2n)。
O(log2n)的這個2時間上是隨著代碼變化的。如果i = i*3,那麼時間復雜度就是O(log3n)
回顧下log的理解(這是初中知識點):
如果a的x次方等於N(a>0,且a≠1),那麼熟x就叫做以a為底的對數(logarithm),記作x=logaN.
其中,a叫做對數的底數,N叫做真數,x叫做「以a為底N的對數」。
3.5.3:線性階O(n)
代碼如下:
說明:
這段代碼,for循環裡面的代碼會執行n次。因此它所消耗的時間隨著n的變化而變化的,因此這類代碼都是可以用O(n)來表示它的時間復雜度。
3.5.4:線性對數階O(nlogn)
代碼如下:
說明:
線性對數階O(nlogN)其實非常容易理解的。將時間復雜度為O(logn)的代碼循環了N次的話,那麼它的時間復雜度就是n*O(logn),也就是O(nlogN)
3.5.5:平方階O(n2)
代碼:
說明:
平方階O(n2)就容易理解了。如果把O(n)的代碼再嵌套循環一遍,它的時間復雜度就是O(n2),
上圖中的代碼起始就是嵌套了2層n循環,它的時間復雜度就是O(n*n),即時O(n2)。如果將其中一層循環的n修改成m,那麼它的時間復雜度就變成了O(m*n).
3.5.6:立方階O(n3)、K次方階O(n^k)
說明:參考上面的O(n2)去理解就好了。O(n3)起始就相當於是三層n循環了。其他的一次類推。
3.6:平均時間復雜度和最壞時間復雜度
平均時間復雜度:
是指所有可能的輸入實例均以概率出現的情況下,該演算法的運行時間
最壞時間復雜度:
是指在最壞情況下的時間復雜度稱為最壞時間復雜度。一般討論時間復雜度均是最壞情況下的時間復雜度。
這樣做的原因:最壞情況下的時間復雜度是演算法在任何輸入實例上運行時間的界限。這就保證了演算法的運行時間不會比最壞情況更長了。
平均時間復雜度和最壞時間復雜度是否一致,和演算法有關。具體如下圖:
四:演算法的空間復雜度
空間復雜度介紹
類似於時間復雜度的討論。一個演算法的空間復雜度(Space Complexity)定義為該演算法所消耗的存儲空間,它也是問題規模n的函數;
空間復雜度是對一個演算法在運行過程中臨時佔用存儲空間大小的量度。有的演算法需要佔用臨時工作單元數與解決問題的規模n有關。它們隨著n的增大而增大,當n較大的時候,將佔用較多的存儲單元(存儲空間)。例如:在快排(快速排序)和歸並排序演算法就屬於這種情況。
在做演算法分析的時候,主要討論的是時間的復雜度。因為從用戶的使用體驗上來看,更看重的是程序執行的速度的快慢。一般緩存產品(比如Redis)和技術排序演算法本質就是拿空間換時間的。
下節預告:
下節我們將講講冒泡排序和選擇排序。使用的是圖解+代碼一步一步推導出來演示的。歡迎大家一起學習
『陸』 一位出色的程序員的數學知識應該達到怎樣的程度
離散數學對程序員來說非常重要,還有組合數學、線性代數、概率論、數論等等,即使你將來不做研究,這些基礎知識也能極大地提高你的水平。計算機科學對離散數學的要求很高,建議你先學習前面提到的這些課程,然後學習計算機演算法和數據結構,再配合到網上的在線題庫做題,過程很艱辛,但是對你的幫助會很大。
推薦書目:
《具體數學》(先學完前面的數學課程,在水平有一定進步以後再看)
《演算法導論》(應該人手一本的好書)
簡單來說,學數學的目的,一方面是活躍你的思維;另一方面是為了深入學習演算法打基礎,設想一下,同樣的問題,普通人的程序要幾十分鍾甚至幾小時幾天才能解決出來,甚至根本無法解決,而你精心設計的程序卻能在1秒內解決出來,這就是數學的魅力、演算法的魅力。
『柒』 正學C語言,不明白程序和演算法有什麼區別我理解的是演算法是解決問題的步驟,可是看看程序似乎也是如此啊
有一句經典的話:程序=演算法+數據結構。演算法是解決問題的步驟,演算法是一種思想。比如:計算1加到100的和,那麼(1)你可以從1開始一個一個的加,直到100;(2)(1+100)*50;這兩種解決問題的方法就是演算法。而這種描述計算機不能理解,因此,可以用C語言或其它語言把它寫出來,讓它可以在計算機上運行,這就是一個程序。程序可以理解為對演算法的一種包裝,目的就是讓它可以在計算機上能運行。
『捌』 常用的數據挖掘演算法有哪幾類
常用的數據挖掘演算法分為以下幾類:神經網路,遺傳演算法,回歸演算法,聚類分析演算法,貝耶斯演算法。
目前已經進入大數據的時代,所以數據挖掘和大數據分析的就業前景非常好,學好大數據分析和數據挖掘可以在各個領域中發揮自己的價值;同時,大數據分析並不是一蹴而就的事情,而是需要你日積月累的數據處理經驗,不是會被輕易替代的。一家公司的各項工作,基本上都都用數據體現出來,一位高級的數據分析師職位通常是數據職能架構中領航者,擁有較高的分析和思辨能力,對於業務的理解到位,並且深度知曉公司的管理和商業行為,他可以負責一個子產品或模塊級別的項目,帶領團隊來全面解決問題,把控手下數據分析師的工作質量。
想要了解更多有關數據挖掘演算法的信息,可以了解一下CDA數據分析師的課程。課程教你學企業需要的敏捷演算法建模能力,可以學到前沿且實用的技術,挖掘數據的魅力;教你用可落地、易操作的數據科學思維和技術模板構建出優秀模型,只教實用干貨,以專精技術能力提升業務效果與效率。點擊預約免費試聽課。
『玖』 全世界最強的演算法平台codeforces究竟有什麼魅力
簡單介紹一下codeforces這個網站,codeforces位於宇宙編程最強的毛國。據說最早是由俄羅斯的一群大學生維護的,它最大的特點就是代碼和題解的公開。所有人都可以隨意查看其它大牛的代碼,可以說是非常具有開源精神了。
codeforces很大的特點就是題目兼容並蓄,什麼難度等級的題目都可以找到。並且題目很有意思,往往思維陷阱比較多,也就是思維題比較多。對於數據結構以及演算法的考察相對弱一些,更多的時候往往是告訴你用什麼演算法你也不知道怎麼做……
codeforces另外一個很大的特點就是它有自己的上分系統,基本上每周會舉辦一到兩次在線的演算法比賽。一般的比賽時長是兩個小時,只要注冊賬號就可以免費參加。我記得當年第一次參加比賽會獲得一個初始分是1500,然後根據你在比賽當中的表現上分或者減分。由於參加的選手水平實力強度不一,所以它開設了好幾個檔次(div),不同層次的選手面對的題目難度也不一樣,這樣保證了大家都可以愉快地參賽。
codeforces在比賽的時候只會測試一小部分數據,真正的測試集會放到賽後進行測試。所以在比賽中測試通過的代碼,只是通過了小數據驗證,很有可能有隱藏的問題沒被發現。當你通過了這道題之後,你就可以去查看其他通過人的代碼,去分析它們有沒有問題,如果發現了bug,可以構造一份數據hack掉他的提交。hack成功之後,你會獲得分數的獎勵。
你可以雙擊打開其他人的提交記錄,去閱讀他們的代碼。到了比賽後期,能做的問題做的差不多了之後,就進入了緊張刺激的互相hack階段。講道理,這比只是單純做題的競賽要有趣多了。
以前我們acm集訓隊經常晚上一起打codeforces的比賽,有時候看到隊友在一個房間里,還會互相關注一下近況,互相hack一把,不得不說現在懷念起來還是非常有意思的。
好了,關於codeforces網站就介紹到這里了,如果你也對演算法感興趣的話,不妨試著用一下它吧,相信你也會找到演算法的樂趣。
『拾』 最近打算看演算法導論,在如何看方面有什麼好的建議
演算法導論,不適合入門,建議有數據結構和高等數學基礎再讀
這書上面有些內容太難了,剛開始不適合全看,挑些自己能看懂的來學。
很適合演算法初學者體會演算法的魅力.這本書講解的很全面.演算法都用偽碼實現.對編程語言要求不高.書的前幾章是一些數學和概率基礎和演算法分析的一些說明.後面幾章是一些演算法的描述.對NP問題感興趣的話.可以看看這本書的VII部分中的NP-Completeness.我覺得這本書比較好的一部分是它的附錄部分.對前面的一些背景知識公式進行了詳細的闡述和證明以及一些專有名詞進行了索引方便檢索.這本書在國內目前只有英文版的.但南大有個中文版的(不過他們太無恥了居然說是他們自己編著)我看了那個版本的.其實是第一版的中文翻譯叫<現代計算機常用數據結構和演算法>.其他的我想我不需要多說了.有興趣的可以去體會一下,