【算法基础】排列与组合

来源:互联网 发布:易语言自动更新源码 编辑:程序博客网 时间:2024/05/16 08:48

1. 排列 Permutation

排列的数学公式:


1.1 对数组元素进行全排列

一个数组int a[3] = {1, 2, 3}; 对其进行全排列:
1, 2, 3;
1, 3, 2;
2, 1, 3;
2, 3, 1;
3, 2, 1;
3, 1, 2;

1.1.1 全排列的递归实现


2,1,3;与3,2,1;是通过交换1与3,2得到的;                           (k = 1)
将1,2,3;的第2,3个数交换得到1,3,2;                                     (k = 2)
同理根据2,1,3;得到2,3,1;通过3,2,1;得到3,1,2;    (k = 2)

因此,全排列就是从第一个元素起分别与后面的元素交换


#include <cstring>#include <iostream>using namespace std;void swap(int& a, int& b){int temp = a;a = b;b = temp;}void print(int array[], int size, int index){cout<<"The "<<index<<" permutation is: ";    for (int i = 0; i < size; i++){cout<<array[i]<<" ";}cout<<endl;}void permutation(int array[], int size, int k){    if (k == (size - 1)){    // end recursionstatic int index = 0;print(array, size, ++index);}else{for (int i = k; i < size; i++){swap(*(array + k), *(array + i));permutation(array, size, k + 1);swap(*(array + k), *(array + i));}}}int main() {int array[] = {1,2,3, 4};  permutation(array, sizeof(array)/sizeof(int), 0);return 0;}

1.1.2 去掉重复元素的全排列的递归实现

对于1,2,2;第一个数与第二个数交换得到2,1,2;然后考虑第一个数与第三个数交换,由于第三个和第二个数相同,所以第一个数不再与第三个数交换;
全排列中去掉重复的规则:去重复的全排列就是从第一个元素起分别与它后面非重复出现的元素交换

#include <cstring>#include <iostream>using namespace std;void swap(int& a, int& b){int temp = a;a = b;b = temp;}/** * whether there is the same element between [start, end) as end value */bool isSwap(int array[], int size, int start, int end){for (int i = start; i < end; i++){if (array[i] == array[end]){return false;}}return true;}void print(int array[], int size, int index){cout<<"The "<<index<<" permutation is: ";    for (int i = 0; i < size; i++){cout<<array[i]<<" ";}cout<<endl;}void permutation(int array[], int size, int k){    if (k == (size - 1)){    // end recursionstatic int index = 0;print(array, size, ++index);}else{for (int i = k; i < size; i++){// before swap the element[k] and element[i], check if there is redundant element between [k, i) if (isSwap(array, size, k, i)){    swap(*(array + k), *(array + i));    permutation(array, size, k + 1);    swap(*(array + k), *(array + i));}}}}int main() {int array[] = {1,2,2};  permutation(array, sizeof(array)/sizeof(int), 0);return 0;}


2. 组合 Combination

组合的数学公式:


2.1 全组合

2.1.1 二进制转换法求全组合

如字符: a, b, c, d, e:将每一个组合与一个二进制数对应起来;枚举二进制数的同时,枚举每个组合:
00000  <----->  null
00001  <----->  e
00010  <----->  d
...
...
11111  <----->  abcde
所有的二进制数位于:[00001, 11111] / [00001, 100000);

#include <cstring>#include <iostream>using namespace std;/** * print the combination through the binary number. */void printSubCombination(int array[], int size, int binary){cout<<"The "<<binary<<" combination: ";for (int i = 0; i < size; i++){// find the array element which exists in the binary number. if (binary & (1<<i)){cout<<array[i]<<" ";}}cout<<endl;}/** * enumerate all the binary number between [1, 1xxx);  * e.g. 3 elements, 1<<3 = 1000, all the combination are between [001, 111] / [100,1000)  */void combination(int array[], int size){    for (int i = 1; i < (1<<size); i++){// print the combination result through the binary number.printSubCombination(array, size, i);}}int main() {int array[] = {1,2,3};  combination(array, sizeof(array)/sizeof(int));return 0;}



2.2 n中选m组合

2.2.1 01转换法

例如从5个数中选择3个进行组合,将11100通过01转换成00111结束。