最大值的選取

2022-02-17 14:17:55 字數 1416 閱讀 5436

此文**  

如果問題中各資料的範圍明確,那麼無窮大的設定不是問題,在不明確的情況下,很多程式設計師都取0x7fffffff作為無窮大,因為這是32-bit int的最大值。如果這個無窮大只用於一般的比較(比如求最小值時min變數的初值),那麼0x7fffffff確實是乙個完美的選擇,但是在更多的情況下,0x7fffffff並不是乙個好的選擇。

很多時候我們並不只是單純拿無窮大來作比較,而是會運算後再做比較,例如在大部分最短路徑演算法中都會使用的鬆弛操作:

if (d[u]+w[u][v]

除了要滿足加上乙個常數依然是無窮大之外,我們的常量還應該滿足「無窮大加無窮大依然是無窮大」,至少兩個無窮大相加不應該出現災難性的錯誤,這一點上0x7fffffff依然不能滿足我們。

即,0x7fffffff不能滿足無窮大 + 常數 = 無窮大  且 不能滿足無窮大 + 無窮大 = 無窮大

所以我們需要乙個更好的傢伙來頂替0x7fffffff,最嚴謹的辦法當然是對無窮大進行特別處理而不是找乙個很大很大的常量來代替它(或者說模擬它),但是這樣會讓我們的程式設計過程變得很麻煩。在我讀過的**中,最精巧的無窮大常量取值是0x3f3f3f3f,我不知道是誰最先開始使用這個精妙的常量來做無窮大,不過我的確是從一位不認識的acmer(id:staginner)的部落格上學到的,他/她的很多**中都使用了這個常量,於是我自己也嘗試了一下,發現非常好用,而當我對這個常量做更深入的分析時,就發現它真的是非常精巧了。

0x3f3f3f3f的十進位制是1061109567,也就是10^9級別的(和0x7fffffff乙個數量級),而一般場合下的資料都是小於10^9的,所以它可以作為無窮大使用而不致出現資料大於無窮大的情形。

另一方面,由於一般的資料都不會大於10^9,所以當我們把無窮大加上乙個資料時,它並不會溢位(這就滿足了「無窮大加乙個有窮的數依然是無窮大」),事實上0x3f3f3f3f+0x3f3f3f3f=2122219134,這非常大但卻沒有超過32-bit int的表示範圍,所以0x3f3f3f3f還滿足了我們「無窮大加無窮大還是無窮大」的需求。

最後,0x3f3f3f3f還能給我們帶來乙個意想不到的額外好處:如果我們想要將某個陣列清零,我們通常會使用memset(a,0,sizeof(a))這樣的**來實現(方便而高效),但是當我們想將某個陣列全部賦值為無窮大時(例如解決圖論問題時鄰接矩陣的初始化),就不能使用memset函式而得自己寫迴圈了(寫這些不重要的**真的很痛苦),我們知道這是因為memset是按位元組操作的,它能夠對陣列清零是因為0的每個位元組都是0,現在好了,如果我們將無窮大設為0x3f3f3f3f,那麼奇蹟就發生了,0x3f3f3f3f的每個位元組都是0x3f!所以要把一段記憶體全部置為無窮大,我們只需要memset(a,0x3f,sizeof(a))。

即,0x3f3f3f3f能表示無窮大 且 滿足無窮大 + 常數 = 無窮大  且 滿足無窮大 + 無窮大 = 無窮大 且 易初始化

所以在通常的場合下,0x3f3f3f3f真的是乙個非常棒的選擇。

最大值的選取

如果問題中各資料的範圍明確,那麼無窮大的設定不是問題,在不明確的情況下,很多程式設計師都取0x7fffffff作為無窮大,因為這是32 bit int的最大值。如果這個無窮大只用於一般的比較 比如求最小值時min變數的初值 那麼0x7fffffff確實是乙個完美的選擇,但是在更多的情況下,0x7ff...

選取擁有某個列的最大值的行

任務 找出最貴物品的編號 銷售商和 這很容易用乙個子查詢做到 select article,dealer,pricefrom shopwhere price select max price from shop 另乙個解決方案是按 降序排序所有行並用mysql特定limit 子 句只得到第一行 se...

滑動視窗的最大值 佇列的最大值

請定義乙個佇列並實現函式max得到佇列裡的最大值,要求函式max push back和 pop front的時間複雜度都是o 1 在佇列中維護乙個儲存最大值的佇列,當pop和push操作的同時也對最大值佇列進行維護。當彈出的時佇列中的最大值時,也彈出最大值佇列的頭,當壓入新值時,對最大值佇列從後向前...