【算法基础】排列与组合

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 recursion
		static 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 recursion
		static 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结束。




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值