從零開始的暴力算法之旅

這幾天沒更算法,一個主要的原因是我發(fā)現(xiàn)自己在解決一個問題時沒有一個系統(tǒng)的思考方法,我意識到這個問題的嚴重性。想必大家都經(jīng)歷過,面對復雜的問題只是傻乎乎的盯著顯示器,或者不經(jīng)過深思熟慮就開始敲打鍵盤,結果還要辛辛苦苦修改一塌糊涂的代碼。
一本書上說道:與通常所想不同,支配設計算法的并不是一時出現(xiàn)的靈感,而是許多策略性的選擇。構想算法不僅需要理解問題的特性,還要理解執(zhí)行時間和占用內存空間之間的對立關系,而且還要選擇適當?shù)臄?shù)據(jù)結構。有些算法會共享出解決問題時最重要的領會,將之積累起來就會領悟到一種模式。
只讀這一段會覺得有點難以理解但好似有很有道理,其實,我這幾天學到了一種如何思考問題的方法,總結起來就一句話:化繁為簡。接下來的文章我會通過實例逐一詮釋我的領悟所得。
我們最常見的錯誤就是把簡單的問題復雜化,比如前幾天去飯店吃飯,一個二年級的小朋友有一道數(shù)學題:一根木棍長22米,請問需要截取幾次才能將其分為長度都為2米的木棍。答案很簡單:22/2。但是我卻本能的告訴那孩子是log2(22/2)?,F(xiàn)在想來我都笑了,二分算法寫多了。
所以,為了避免類似的錯誤,每當我們遇到問題時應當先自問:能否用暴力的方法解決,并且是否能否優(yōu)雅的解決【這體現(xiàn)了一個程序員是否有一顆優(yōu)雅編程的心】。
接下來看一道問題:
求從0開始按順序標號的n個元素中,選擇4個元素的所有可能的組合。假設n=7,那么大家就會想到寫一個4重循環(huán)就好,看起來是這個樣子:
for(int i = 0; i < n; ++i)
for(int j = i+1; j < n; ++j)
for(int k = j+1; k < n; ++k)
for(int l = k+1; l < n; ++l)
cout<<i<<j<<k<<l<<endl;
但是若是選擇5個數(shù)字的全排列呢,7個,8個呢,是不是得手動在增加循環(huán)次數(shù),比追女生都麻煩是不是。要是我們將每一個循環(huán)看成一個遞歸的話,就很容易優(yōu)雅解決了。
//n:元素總量
//picked:已選元素的序號
//toPick:還需選擇元素的數(shù)量
則構成的飄逸的代碼是下面這樣的:

include<iostream>

include<vector>

using namespace std;

void printPicked(vector<int> & picked){
for(int i = 0; i<picked.size(); i++){
cout<<picked[i];
}
cout<<endl;
}
void pick(int n, vector<int>& picked, int toPick){
if(toPick == 0) {
printPicked(picked);return;
}
int smallest = picked.empty() ? 0 : picked.back() + 1;
for(int next = smallest; next < n; ++next){
picked.push_back(next);
pick(n,picked,toPick-1);
picked.pop_back();
}
}
int main(){
int n = 0;
cin >> n;
vector<int> picked;
pick(10,picked,n);
}

是不是很棒。。。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容