1. 程式人生 > 其它 >怒刷排列組合,如何解“排列組合”一類的問題

怒刷排列組合,如何解“排列組合”一類的問題

技術標籤:C/C++資料結構及演算法演算法資料結構

怒刷排列組合

在刷Leetcode題目時,時常會看到一些大佬提出時間複雜度為O(1)的題解,而我還在O(nm)O(n)之間如此反覆,細細品味,其實有一類題目是經常可以爆出O(1)的解法的,這一類題目背後的數學依據就是排列組合

顧名思義,排列即排列,組合即組合,排列組合主要是用來解決做一件事情有多少種方法或者某件事發生的概率是多少的問題。例如小明從家到學校可以選擇步行、騎車、坐計程車。**問題1:**小明從家到學校有幾種出行方式?**問題2:**小明從家到學校再返回家中,有幾種出行方式?

針對上述的兩個問題,其實是引入了排列組合問題中最基本的兩個原理分類加法原理

分步乘法原理

分類加法原理:做一件事情,完成它有N類方法,在第一類方法中有M1種不同的方法,第二類方法中有M2種不同的方法……第m類方法中有Mn種不同的方法,那麼完成這件事共有M1+M2+…+Mn種不同的方法。

分步乘法原理:做一件事情,完成它需要n個步驟,做第一個步驟有M1種不同的方法,做第二個步驟有M2種不同的方法,第n個步驟有Mn種不同的方法,那麼完成這件事共有M1 · M2 · … · Mn種不同的方法。

分類加法原理就是說一個任務被分成了幾類,就有幾項相加,本質是每一類方法均能獨立的完成該任務;而分步乘法原理是分成幾步,就有幾項相乘,其本質是缺少任何一步均無法完成任務,每一步是不可缺少的環節

有了對上述兩個原理的理解,就可以更好的體會什麼是排列、組合了,其定義如下:

排列:從n個不同的元素中任取m個(m≤n)元素,按照一定的順序排列成一列,叫做從n個不同的元素中取出m個元素的一個排列。

組合:從n個不同的元素中任取m個(m≤n)元素併為一組,叫做從n個不同的元素中取出m個元素的一個組合。

究其定義不難發現,排列和組合都是從n個元素中取出m個元素,而不同點則是排列要求取出的元素具有一定的順序,組合對取出元素的順序不做要求。反之就可以在做題的時候抓住是否有序來使用不同的解題方法。

當然,做題時只會區分問題屬於排列問題還是組合問題是不夠的,往往題目會讓求解出排列數和組合數為多少,甚至會要求打印出其中的每一項。

  • 針對“求解排列數和組合數”的問題

這一類問題就是題解中常常爆出時間複雜度為O(1)的問題,很多問題題目極其拗口,給人的第一感覺就是,這題也太複雜了,連在紙上寫出可能的結果都很難,其實,透過現象看本質,其中有一類問題背後的數學原理就是排列組合,一旦發現這是一類排列組合的問題,剩下的就不必多說了吧,直接上公式,用最快的時間就能計算出最準確的答案。

這裡再把所謂的公式複習一下:

排列數:從n個不同的元素中任取m個(m≤n)元素所有排列的個數,叫做從n個不同的元素中取出m個元素的排列數,記為A(n, m)。

其中, A(n, m) = n! / (n - m)!

組合數:從n個不同的元素中任取m個(m≤n)元素所有組合的個數,叫做從n個不同的元素中取出m個元素的組合數,記為C(n, m)。

其中,C(n, m) = n! / ( m! · (n - m)! )

列舉一道題目,來體會一下排列組合的魅力。如題:

從2×2網格的左上角開始,並且只能向右和向下移動,到右下角有6條路線。那麼問在20×20網格中有多少條這樣的路線?

在這裡插入圖片描述

每次拿到這樣的題目,我個人的習慣就是直接拿筆在紙上開始畫出可能的結果,雖然看著2×2的情況下只有6種不同的路線,但是到了4×4的時候,紙上已經畫的一團糟了,哈哈