由於c++語言的高效性與便利性,在進行一些演算法設計的時候我總是會選擇用c++。其中我遇到過的乙個錯誤讓我印象深刻。這是乙個關於線段樹和運算子優先順序的故事。
基本的遞迴式的線段樹看起來大致像這樣:
#include #include#include
using
namespace
std;
const
int n = 1000001
;struct
node
node[n * 4
];void build( int i, int l, int
r )int
main ()
當然,node結點中你會新增上你需要維護的變數,例如sum、max、min等各種稀奇古怪的東西,這裡不做討論。
但是,乙個很明顯的問題就是:結點的數量往往很多,動輒幾百萬,還是遞迴形式的。而改成非遞迴顯得有點難。考慮到其中有大量的乘法運算,於是我寫出了如下改進的**:
#include #include#include
using
namespace
std;
const
int n = 1000001
;struct
node
node[n
<< 2
];void build( int i, int l, int
r )int
main ()
用移位運算子來代替乘除法,貌似是個不錯的選擇。但是這組程式卻無法通過測試用例。
通過跟蹤建樹過程,發現原因是移位運算子 << 的優先順序要低於 +。
所以 build( i << 1 + 1, mid + 1, r ); 其實是 build( i << ( 1 + 1 ), mid + 1, r );
而我本意則是 build( ( i << 1 ) + 1, mid + 1, r );
原來加括號很重要!尤其是當你不知道優先順序的時候。
但是當你知道了優先順序以後,你可能會寫出更加優雅、快速的**:
build( i << 1 | 1, mid + 1, r );
原來,優先順序很重要!
讓我印象深刻的IT名言(技術類)
1 premature optimization is the root of all evil donald knuth 解釋 過早的優化是萬惡之源。first do thing right,then do thing fast。例外 你很清楚現在就站在系統的熱點上,程式設計時就應該直接考慮效率。...
記乙個印象深刻的點名招數
在大學裡,老師們的點名方式各有各的不同,不過,我印象最深的還是有一學期的英語口語課點名。有乙個學期是乙個英國老師給我們上口語課。第一節課,他給我們布置了乙個作業 下次上課每人帶上一張1寸照。儘管不確定老師具體要用 來幹什麼,不過,第二節課我們還是帶上了 第三次上課,有兩個同學沒有來。口語老師說,好像...
軟體測試中遇到的印象深刻的問題及反思
軟體測試中遇到的比較印象深刻的問題 專案名稱是某幼兒園報名 首先我介紹一下這個專案,這個專案是用來給某地區的家長搶報幼兒園名額而服務的,畢竟有的幼兒園人氣比較火爆,因此會出現人多名額少的情況,從而比較注重測試環節,保證家長報名成功。為了提高效能,對一些常用的前端檔案 js,css等檔案 進行了cdn...