排列組合演算法

2021-07-27 06:25:20 字數 2857 閱讀 8041

組合演算法的思路是開乙個陣列,其下標表示1到m個數,陣列元素的值為1表示其下標代表的數被選中,為0則沒選中。

初始化,將陣列前n個元素置1,表示第乙個組合為前n個數。

從左到右掃瞄陣列元素值的「10」組合,找到第乙個「10」組合後將其變為「01」組合,同時將其左邊的所有「1」全部移動到陣列的最左端。

當第乙個「1」移動到陣列的m-n的位置,即n個「1」全部移動到最右端時,就得到了最後乙個組合。

例如求5中選3的組合:

111

00//1,2,3 11

010//1,2,4 10

110//1,3,4 01

110//2,3,4 11

001//1,2,5 10

101//1,3,5 01

101//2,3,5 10

011//1,4,5 01

011//2,4,5 00

111//3,4,5

c++**如下:

class combination 

else

tag = false;}}

private:

void

displayarray(int *a, int n)

// 0到n-1,把1移到最左邊

void movezeros(int *a, int n)

right++;}}

};

從n個數中選取編號最大的數,然後在剩下的n-1個數裡面選取m-1個數,直到從n-(m-1)個數中選取1個數為止。

從n個數中選取編號次小的乙個數,繼續執行1步,直到當前可選編號最大的數為m。

c++**如下

class combination 

private:

void

displayarray(int *a, int n)

void func(int *a, int n, int m, const

int n)

for (int i = n - 1; i >= m - 1; i--)

}};

如果集合是,那麼這個集合中元素的所有排列是,顯然,給定n個元素共有n!種不同的排列.

如果給定集合是,可以用下面給出的簡單演算法產生其所有排列,即集合(a,b,c,d)的所有排列有下面的排列組成:

(1)以a開頭後面跟著(b,c,d)的排列

(2)以b開頭後面跟著(a,c,d)的排列

(3)以c開頭後面跟著(a,b,d)的排列

(4)以d開頭後面跟著(a,b,c)的排列

這顯然是一種遞迴的思路,於是我們得到了以下的實現:

c++**如下

class permutation 

private:

void

displayarray(int *a, int n)

void func(int *a, int m, const

int n)

for (int i = 0; i < n; i++) }}

};

全排列生成演算法的乙個重要思路,就是將集合a中的元素的排列,與某種順序建立一一對映的關係,按照這種順序,將集合的所有排列全部輸出。這種順序需要保證,既可以輸出全部的排列,又不能重複輸出某種排列,或者迴圈輸出一部分排列。

字典序就是用此種思想輸出全排列的一種方式。這裡以a來說明用字典序輸出全排列的方法。

首先,對於集合a的某種排列所形成的序列,字典序是比較序列大小的一種方式。

以a為例,其所形成的排列1234<1243,比較的方法是從前到後依次比較兩個序列的對應元素,如果當前位置對應元素相同,則繼續比較下乙個位置,直到第乙個元素不同的位置為止,元素值大的元素在字典序中就大於元素值小的元素。

上面的a1[1…4]=1234和a2[1…4]=1243,對於i=1,i=2,兩序列的對應元素相等,但是當i=2時,有a1[2]=3 < a2[2]=4,所以1234 < 1243。

使用字典序輸出全排列的思路是,首先輸出字典序最小的排列,然後輸出字典序次小的排列,……,最後輸出字典序最大的排列。

這裡就涉及到乙個問題,對於乙個已知排列,如何求出其字典序中的下乙個排列。這裡給出演算法。

對於排列a[1…n],找到所有滿足a[k] < a[k+1] (0< k < n-1)的k的最大值,如果這樣的k不存在,則說明當前排列已經是a的所有排列中字典序最大者,所有排列輸出完畢。

在a[k+1…n]中,尋找滿足這樣條件的元素l,使得在所有a[l]>a[k]的元素中,a[l]取得最小值。也就是說a[l]>a[k],但是小於所有其他大於a[k]的元素。

交換a[l]與a[k].

對於a[k+1…n],反轉該區間內元素的順序。也就是說a[k+1]與a[n]交換,a[k+2]與a[n-1]交換,……,這樣就得到了a[1…n]在字典序中的下乙個排列。

這裡我們以排列a[1…8]=13876542為例,來解釋一下上述演算法。首先我們發現,1(38)76542,括號位置是第一處滿足a[k] < a[k+1]的位置,此時k=2。

所以我們在a[3…8]的區間內尋找比a[2]=3大的最小元素,找到a[7]=4滿足條件,交換a[2]和a[7]得到新排列14876532,對於此排列的3~8區間,反轉該區間的元素,將a[3]-a[8],a[4]-a[7],a[5]-a[6]分別交換,就得到了13876542字典序的下乙個元素14235678。

下面是該演算法的實現**:

class permutation }}

private:

void

displayarray(int *a, int n)

};

排列組合演算法

在開發的過程中很難免會到排列組合,剛開始通過for迴圈來搞定。但是對於工作了近五年的我而已,不能像 新人那樣做了。如果所要組合的集合大於40,你不可能寫40個for迴圈吧!這裡使用了數學的演算法,到底是啥演算法,高人也沒說!不過我把它的思想提公升了一下。如下 ifndef combination h...

排列組合演算法

1.排列演算法 include define max num 100 void print int n,int num void swap int a,int b int arrange int i,int n,int num i return count int combination int u...

排列組合演算法

題目 求 1 一組數字的全排列 2 一組數字中某幾個數字的組合 一 排列演算法 全排列是將一組數按一定順序進行排列,如果這組數有n個,那麼全排列數為n 個。現以為例說明如何編寫全排列的遞迴演算法。如下圖所示 上圖中,第一層s1表示第乙個數分別與第1 2 3個數交換位置,如123是1和第乙個數1交換,...