【算法】学习笔记(0):算法初探(逻辑抽象 + 示例 + 代码实现)
什么是算法?
人生皆算法,算法的本質(zhì),是解決問(wèn)題的方法,遇到問(wèn)題,尋找答案,解決問(wèn)題,是作為一個(gè)人,一生都在做的事情。
算法是人類思維的產(chǎn)物,是解決問(wèn)題的方案,并且,它能夠映射到計(jì)算機(jī)世界去實(shí)現(xiàn),完成一些人類不擅長(zhǎng)的事情,比如大量重復(fù)的計(jì)算。
算法很有魅力,它很特別,但是并不神秘,我們時(shí)時(shí)刻刻都在運(yùn)用著算法背后的“解決問(wèn)題”的思想去生活,去過(guò)著每一天。
用計(jì)算機(jī)思維去思考問(wèn)題
算法是普通的,也是特別的,它是人類使用計(jì)算機(jī)思維思考的產(chǎn)物,能夠讓人類更加充分地利用計(jì)算機(jī)這個(gè)人類發(fā)明的工具,這也是信息時(shí)代特有的產(chǎn)物。
既然是計(jì)算機(jī)思維,當(dāng)然有其特點(diǎn):
概念不重要,理解即可,不必記憶,不必急于掌握,直接看實(shí)例體會(huì)。
“玩具”問(wèn)題
計(jì)數(shù):判斷一個(gè)byte(無(wú)符號(hào)整數(shù))里面有多少個(gè)bit的值是1
算法一
很簡(jiǎn)單的想法,將十進(jìn)制數(shù)轉(zhuǎn)換為一位一位的二進(jìn)制,然后看看是不是1就好了,就是簡(jiǎn)單的數(shù)數(shù)。
// method 1 int cal_1(unsigned char number) {unsigned char count = 0;while (number != 0){int div = number % 2;if (div == 1) {count++;}number /= 2;}return count; }算法二
上面是我們解決問(wèn)題的第一種想法。
下面我們加一種假設(shè),假如內(nèi)存空間足夠大,且使用函數(shù)次數(shù)足夠多,我們是不是可以提高算法的效率?
要知道,1字節(jié)大小的無(wú)符號(hào)整數(shù),一共28 = 256種,如果我們連續(xù)10000次調(diào)用函數(shù),每一次都使用除二取余法(算法1),就大量重復(fù)計(jì)算了,這個(gè)時(shí)候不妨提前算好把結(jié)果存起來(lái),然后直接訪問(wèn)結(jié)果(就像緩存、cache那樣的思想)。
也就是所謂的打表查表
// 計(jì)數(shù):判斷一個(gè)byte(無(wú)符號(hào)整數(shù))里面有多少個(gè)bit的值是1 #include <iostream> using namespace std;int num_table[256] = { 0 };// method 1 int cal_1(unsigned char number) {unsigned char count = 0;while (number != 0){int div = number % 2;if (div == 1) {count++;}number /= 2;}return count; }// method 2 int cal_2(unsigned char number) {return num_table[number]; }int main(){// 存儲(chǔ)答案for (unsigned char i = 0; i < 255; i++) {num_table[(int)i] = cal_1(i);}// 直接訪問(wèn)cout << cal_2(15);return 0; }我們開始使用算法1,存儲(chǔ)了一張表,之后再需要使用的時(shí)候,就能夠直接查表得結(jié)果,而不需要再重復(fù)計(jì)算了,如果調(diào)用100000萬(wàn)次,效率將會(huì)比算法1顯著提高。
當(dāng)然……由于數(shù)據(jù)量對(duì)計(jì)算機(jī)來(lái)說(shuō)太小了還是,測(cè)試不出很大的差異其實(shí)。
如果規(guī)模更大,會(huì)有顯著效果。
算法三
對(duì)于算法一
- 省空間,因?yàn)闆](méi)占用多少數(shù)據(jù)段
對(duì)于算法二 - 省時(shí)間,因?yàn)樘崆皟?chǔ)存好了答案,只需要訪問(wèn)數(shù)組就可以
對(duì)于前面兩種算法,是根據(jù)不同需求不同情況取使用的,但是涉及到了算法設(shè)計(jì)考慮的兩個(gè)維度:時(shí)間和空間。
算法一省空間,費(fèi)時(shí)間,算法二省時(shí)間廢空間,那么能不能兼得?
其實(shí)這種
不走極端取中間的兼得思想
在計(jì)算機(jī)中經(jīng)常需要用到。
我們需要既省時(shí)間又省空間的算法。
與cache類似的設(shè)計(jì)思想
我們可以使用哈希表,采取如下策略
- 如果表中有值,那就直接取
- 如果沒(méi)有,就去計(jì)算,并且存表中
這樣一來(lái),做到了拿走需要的,保存需要的,同時(shí)考慮了時(shí)間和空間兩方面的因素。
我們使用unordered_map完成這件事:
// 計(jì)數(shù):判斷一個(gè)byte(無(wú)符號(hào)整數(shù))里面有多少個(gè)bit的值是1 #include <iostream> #include <unordered_map> using namespace std;typedef std::unordered_map<unsigned char, int> result_map;// method three int cal_3(unsigned char number, result_map &map) {result_map::iterator count = map.find(number);if (count != map.end()) // 在無(wú)序映射表中{cout << "在表中 ";return count->second;}else // 不在表中{cout << "不在表中 ";int result = cal_1(number);map.insert(result_map::value_type(number,result)); // 插入鍵值對(duì)return result;}}int main(){result_map map;cout << cal_3(15, map) << endl; // 不在表中 4cout << cal_3(15, map) << endl; // 在表中 4cout << cal_3(10, map) << endl; // 不在表中 2cout << cal_3(10, map) << endl; // 在表中 2return 0; }這樣,通過(guò)無(wú)序映射表,我們就完成了既節(jié)省時(shí)間,又節(jié)省空間的目的。
小結(jié)
我們來(lái)回顧一下。
對(duì)于這個(gè)問(wèn)題
我們通過(guò)這個(gè)超級(jí)簡(jiǎn)單的例子,初步了解了算法的基本情況,我們繼續(xù)往下進(jìn)行。
連續(xù)子序列和
讓我們體會(huì)一下不同的算法,不同的解決方案,感受一下它們之間的時(shí)間和空間上的性能差異。
一件事情,往往都是很多種解決方案,并且都能到達(dá)彼岸,但是過(guò)程不一樣,走過(guò)的路不同,花的時(shí)間也不同,算法的時(shí)空性能也是一樣的。
充分體會(huì): 計(jì)算機(jī)世界是人類世界的二進(jìn)制映射,與人類生活息息相關(guān)。
算法1:三層循環(huán)
這是一種最樸素的思想了,我們看圖。
因此,我們需要
代碼如下:
#include <iostream> #include <vector> using namespace std;int max_subsequence_sum(const vector<int> &a) {int max_sum = 0;for (int i = 0; i < a.size(); i++) {for (int j = i; j < a.size(); j++) {int current_sum = 0;for (int k = i; k <= j; k++)current_sum += a[k];if (current_sum > max_sum)max_sum = current_sum;}}return max_sum; }int main() {vector<int> a = { 1,3,-1,2 };cout << max_subsequence_sum(a);return 0; }但是,毫無(wú)疑問(wèn),三重循環(huán),時(shí)間消耗過(guò)多了,我們得看看能不能優(yōu)化。
將三重循環(huán)轉(zhuǎn)換為遞歸。
代碼暫不寫
算法2:兩層循環(huán)
算法3:一層循環(huán)
算法4:遞歸
算法比較
小結(jié)
之所以沒(méi)有談及后面的代碼,因?yàn)閷?duì)于初學(xué)者來(lái)說(shuō)比較復(fù)雜,看看就行了,充分體會(huì)的是同一個(gè)問(wèn)題,達(dá)成同一個(gè)目的的情況下,不同算法的差異巨大,這也是算法魅力所在。
致謝
感謝北交大算法MOOC!
總結(jié)
以上是生活随笔為你收集整理的【算法】学习笔记(0):算法初探(逻辑抽象 + 示例 + 代码实现)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 极限竞速地平线5怎么快速买到小吉普
- 下一篇: 【Verilog】数据流建模传输问题:赋