排列組合解法

2021-06-23 04:41:00 字數 2085 閱讀 6835

最近做題遇到了排列組合的題,發現這種問題還挺經典的,以前也沒有總結過,乾脆現在總結一下這一類問題的解法。

這類問題的核心思想就是遞迴與回溯,我們只要把遞迴的方式與回溯的狀態儲存搞清楚了,這類問題基本上都可以用同樣的套路去求解,當然,可能對於某個具體的問題可能會有其他的更優的解法,本文暫且不討論,本文只討論最基本的解法。

排列問題:

先來看排列問題,問題的原型是給定陣列a=輸出所有的排列。首先我們不考慮輸出的順序,其實該問題就是將1固定然後求後面n-1個數的全排列,然後將2固定,求後面n-2個數的全排列...,最後將n-1固定,然後將2放到第一位,計算一次全排列,將n移動到第一位,計算全排列。

這其實就是乙個遞迴過程,例如1 2 3 4的排列可以分為1 [2 3 4]、2 [1 3 4]、3 [1 2 4]、4 [1 2 3]進行排列。

那麼我們來看如何遞迴呢,首先不考慮輸出的順序,如果我們要[1 2 3]的全排列,我們有下面的過程:

1.固定1,計算[2,3]的全排列,

2.固定1,2,計算[3]的全排列,得到[1,2,3] 然後返回到1,

3.交換2,3得到3,2,固定1,3,計算[2]全排列,得到[1,3,2]然後返回狀態14.然後依次類推...

那麼從中我們發現,其實就是不斷的交換後面的元素與當前要遞迴的狀態的第乙個元素交換位置,然後算後面的全排列,那麼這樣我們就可以直接寫出遞迴程式

小插曲:如果我們要求字典序輸出所有的排列呢,所謂字典序是要求輸出按照順序,還拿上面的[1,2,3]來說即輸出:

[1,2,3] [1,3,2] [2,1,3] [2,3,1] [3,1,2] [3,2,1]

我們發現其實就是保證在交換之後後面的資料依然保持遞增有序,那麼我們就可以寫出下面的程式:

void per(int a, int index,int n)

} int main()

;per(a,0,5);

return 0;

}

最基本的排列問題的解的方法就是這樣,可以根據題目的要求再調整一些解法,比如可能輸入資料有重複情況,這種情況下需要先對原陣列排序,然後在交換的時候判斷相鄰的兩項是否相同,如果相同則只需要交換一次,以此來避免重複的情況;再比如說可以重複取元素的情況下,如何排列,這則是控制上面**中index的變化即可。下面說下已知乙個排列,然後求出其之後的下乙個排列是什麼,其實也就是讓你實現下stl中next_permutation的實現。

比如上例中的[1,2,3]為輸入,假設我們給了[1,3,2]作為輸入,其下乙個為[2,1,3],那麼我們來分析如何能得到這樣乙個輸出:

我們知道我們上面求全排列的時候會在每次調整完順序之後重新把順序調整回去,那麼在此我們也模擬這個調整順序,我們從右向左找,找到第乙個非遞增的數的,在這個例子中,我們找到了1,其實這就說明了當前是在算這個位置之後的所有元素的全排列,然後我們從右向左找第乙個遞增序列的元素,這個元素表明交換到的位置,表明到此部分之後的部分都進行了全排列,這裡我們找到了2,那麼交換1和2,然後將第一次找到的費遞增的數的右面的數逆序就得到了下乙個排列,因為這樣既表示計算交換之後的元素的第乙個全排列。

**如下:

void nextpermutation(vector&num) 

auto change = rfirst;

while(change != rlast && *change <= *partation) change++;

swap(*change,*partation);

reverse(rfirst,partation);

}int main()

組合同樣面臨著輸入有重複的情況,採取的措施與排列一樣,先對輸入排序,然後再選擇的時候判斷是否與之前的相等,相等則直接跳過;如果可以重複取的情況下,則控制上面**中的index即可。基本上組合的題可以變形的比較多,比如從n個數中選則任意的數使得和為乙個數k

或者輸出全組合,或者輸出數字的分解,比如輸入3,輸出1 1 1, 1 2 這其實都可以用上面的方法求解,當然還有更優的解這裡就不在敘述了,關於這部分,有幾篇部落格寫得非常不錯,附上位址,大家有興趣可以自行去了解。

演算法題-排列組合問題[

秒殺排列組合(上)————排列篇[

秒殺排列組合(下)————組合篇[

c 排列組合排序 排列組合 組合數專題

書接上回,本期正男老師將帶大家梳理排列組合中組合數的相關考點,組合數考點可以細分為4類,分別為 分類數數問題 分組排序問題 塗色問題以及插棍問題。近六年高考真題中,組合數考點共涉及5道。組合數專題高考真題分布 組合數的定義以及公式如下圖所示。組合數定義 分類數數問題與排列問題中的窮舉問題相似,但分類...

排列組合實現

演算法 與網際網路 組合演算法 本程式的思路是開乙個陣列,其下標表示1到m個數,陣列元素的值為1表示其下標 代表的數被選中,為0則沒選中。首先初始化,將陣列前n個元素置1,表示第乙個組合為前n個數。然後從左到右掃瞄陣列元素值的 10 組合,找到第乙個 10 組合後將其變為 01 組合,同時將其左邊的...

排列組合 HNOI

我這方面比較水就只提供兩道題吧 1.hnoi2008 prison 監獄有連續編號為1.n的n個房間,每個房間關押乙個犯人,有m種宗教,每個犯人可能信仰其中一種。如果相鄰房間的犯人的宗教相同,就可能發生越獄,求有多少種狀態可能發生越獄此題略水,屬於hnoi送分題系列,用補集的思想可以輕鬆過。可能越獄...