演算法技巧總結

2021-06-06 03:31:02 字數 2406 閱讀 4640

1.排序對演算法效能的影響

大家都知道排序演算法,這個應該不是很難了吧,技巧在於很多時候可以利用排序演算法來提供效能,比如: 

例1:給定乙個陣列a[n],求陣列中是否存在兩個數的和等於給定值sum並輸出? 

這個問題很常見,解決方法有很多種,這裡我就不贅述。這裡採用雙指標遍曆法的。陣列不一定有序,我們這裡先不假定排序(即裡邊的資料不是有序的),這時按照常規想法,則用一下迴圈判斷: 

如果a[i]+a[j] == sum,顯然,這裡i的範圍是0~n,j的範圍也是n~i。每當i++時,j都要從n開始遞減,這樣沒有一點智慧型的效果,明顯會增加迴圈的次數。但如果我們對陣列提前進行排好序呢(提前就有序就最好)? 

在陣列有序的情況下,分下邊的三種情況說明:

如果a[i]+a[j] == sum,那麼很顯然,只要輸出這兩個數,並把指標i+1和j-1指向下乙個數即可。

如果a[i]+a[j] > sum,說明當前遍歷的數值偏大,所以可以把j-1以減小和的值,在繼續比較. 

如果a[i]+a[j] < sum,說明當前遍歷的數值偏小,同樣為了加大和可以把i+1。

這時,多了些智慧型的味道哦,總的時間複雜度取決於排序即o(nlogn)。

2.去其糟粕,留其精華.刪減留存相結合

這叫什麼意思呢?其實是這樣的,我們說當乙個問題正面不好回答時,那就從反面排除,最後的那乙個當然就是正確的了: 

例二:某論壇有乙個「水王」,經常發帖,據說該「水王」發帖數目超過了帖子總數的一半,那麼如何在id發帖列表中快速的查詢到這一「水王」? 

這道題如果直接去求這個水王,方法也不少,例如按發帖數對使用者id進行排序排序,但是這至少是o(nlogn)時間複雜度。實際上從反面出發可能會得到更好的結果:盡可能的去減少解空間,把不可能的去除掉,留下的自然是要求的的解。 

分析如下: 每次去除兩個不同id的發帖,由於預設水王發帖超過一半,那麼去除任何兩個不同id後仍然是超過一半的,可能會問為什麼?可以這樣想,開始滿足的公式是 x>y/2(x代表水王id在列表中存在的總數,y代表所有id的條目數),那麼減去兩個不同id後,最壞情況,這兩個不同id中有乙個是水王的id,所以就有(x-1)/(y-2) > (y/2-1)/(y-2) > 1/2,即仍然是大於二分之一的, 所以可以不斷的這樣做直到最終剩下水王id為止。 

實際上這類思想的應用場景可以認為如果看到要求的東西佔總體數量一半以上情況的時候,可以考慮排除法。當然還有其他情況,例如正面求解屢試不行的時候,也可以考慮這樣的方法。

3.經典的公平以小勝**

我自己是常遇見這樣的乙個問題,比如: 

例三:給你乙個n個長度的鍊錶,以及乙個函式,這個函式50%的概率返回0,50%的概率則返回1,問如何用這些條件從這n個鍊錶中隨機的抽取k個節點。注意這裡的n不知道具體的大小哦,也可能很大。

好吧,也許你說你沒見過這樣的題,那麼我們先把問題模擬化處理:在不知道檔案總行數的情況下,如何從檔案中隨機的抽取一行。還是不懂?好吧,再次處理:假設檔案為固定n行,隨機從中取出一行,這時好做了吧,用c的rand()就可以了,可問題是我們的n不是固定的行。固定的好處就在於讓每次取出行的概率對所有行是相等的。當n不固定的時候,概率1/n就不固定,也不相等。那麼怎麼辦呢? 

這裡提到蓄水池抽樣模型,用這個模型重新考慮這個問題:定義取出的行號為choice,第一次直接以第一行作為取出行 choice ,而後第二次以二分之一概率決定是否用第二行替換 choice ,第三次以三分之一的概率決定是否以第三行替換 choice ……,以此類推。這種方法的巧妙之處在於成功的構造出了一種方式使得最後可以證明對每一行的取出概率都為1/n(其中n為當前掃瞄到的檔案行數),換句話說對每一行取出的概率均相等,也即完成了隨機的選取。我們現在用數學歸納法證明剛才的等概率性如下:

(1)當有k=1行,此時第一行被選中的概率為1/1=1;

(2)假設當有k=i行時,此時a行最後被選中的概率是1/i成立。那麼當有k=i+1行時,這時a行最後被選中的概率是它在前邊i行中被選中的概率*後面都沒有被替換的概率,我們知道替換的概率是1/(i+1),那麼不被替換的概率就是i/(i+1),所以:

(3)由k=1,k=i,k=i+1成立可知,對於任意k都有命題成立。

好了,現在我們將問題推廣:如何從未知或者很大樣本空間隨機地取k個數。模擬下即可得到答案,即先把前k個數放入蓄水池,把這k都當成要選的,對第k+1個,我們以k/(k+1)概率決定是否要把它換入蓄水池,換入時隨機的選取乙個作為替換項,這樣一直做下去,對於任意的樣本空間n,對每個數的選取概率都為k/n。也就是說對每個數選取概率相等。這時計算時,任何乙個元素a被選中的概率等於它被選中的概率*[它後面元素b沒有被選中的概率+它後邊元素b被選中(即在後面被選中)*但沒有替換a的概率]. 

最後回到開始的問題,利用蓄水池抽樣思想,先指定前k個節點為所求,並把指標指向第k+1個節點,此時以k/(k+1)決定是否與前k個等概率隨機選定的乙個節點進行替換,替換時隨機選,並以此類推直至結尾。最後剩餘的節點即為所求。

演算法技巧總結

今天和大家講講,在做演算法題時常用的一些技巧。對於平時沒用過這些技巧的人,或許你可以考慮試著去看看在實踐中能否用的上這些技巧來優化問題的解。陣列的下標是乙個隱含的很有用的陣列,特別是在統計一些數字,或者判斷一些整型數是否出現過的時候。例如,給你一串字母,讓你判斷這些字母出現的次數時,我們就可以把這些...

演算法競賽 目標檢測常用技巧總結

以數智重慶.全球產業賦能創新大賽為例,目標檢測的幾種常見的做題技巧如下 針對資料集進行資料提公升 a.需要對資料進行了解,比如有哪些分類,每個分類下各有什麼特點,每個分類下的尺寸是怎樣的,分布是怎樣的 長尾分布,類別不均衡 b.資料出現了什麼樣的問題,應該怎麼去解決這些問題。多樣性,長尾分布 小目標...

一些常用的演算法技巧總結

一些常用的演算法技巧總結 給定兩個字串 s 和 t 編寫乙個函式來判斷 t 是否是 s 的字母異位詞。示例 1 輸入 s anagram t nagaram 輸出 true 示例 2 輸入 s rat t car 輸出 false 說明 你可以假設字串只包含小寫字母。public boolean i...