排 列 组 合 公 式 及 排 列 组 合 算 法 ( 2 0 2 0 )

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

秒杀排列组合(上)————排列篇

首先为什么要写排列组合?因为排列组合在数学中占有重要的地位,其与概率论也有密切关系;并且排列组合问题在求职的笔试,面试出现的概率特别高,而我在网上又没有搜到比较全面题型的文章;同时,我觉得编写排列组合程序对学习递归也是很有帮助的;当然,最重要的原因是排列组合本身就很有趣!所以就总结下排列组合的各种问法,分两篇写:上篇写排列,下篇写组合。

首先从各【导师实操追-女孩教-学】大IT公司的题中总结出排列组合的对象都是整形数组或字符数组,排列问题可以按输入数据分为两大类:输入数据【扣扣】有重复和无重复,又可以按输出数据分为两大类:输出数据有【⒈】重复和无重复;而排列问题也偶尔会考非递归。

首先提一【0】下全排列的几种算法:

1—【1】—字典序法2——递增进位数制法; 3——递减进位数制法【б】4——邻位交换法5——n进制数法6——递归生成法7——循【⒐】环移位法8——回溯法

由于侧【5】重点在输入数据无重复,所以先看输入数据无重复类型:其中又【2】可以分为全排列和分组后排列:

首先写基【6】本的全排列:

1.输出数组a的全排列(不可重复取)

如a={1,2,3}。输出123,132,213,231,312,321

这个是最基本,也是最经典的排列

算法思想:可以输出1加上23的全排列,2加13的全排列,3加上12的全排列,运用递归求比如23的全排列.依次递归下去;比如现在要2开头求全排,首先要交换1,2的位置,让a[0]变为2,在用递归求13的所有全排列,前面加个2就是2开头的所有全排列了,最后运用回溯再把1,2调换回来。

代码清单:

public class PaiLie {

public void runPermutation(int[] a){

getAllPermutation(a, 0);

-*index用于控制如上述分析中2加上13的所有全列的*-

public void getAllPermutation(int[] a,int index){

-*与a的元素个数相同则输出*-

if(index == a.length-1){

for(int i = 0; i a.length; i++){

System.out.print(a[i] + " ");

System.out.println();

return;

for(int i = index; i a.length; i++){

swap(a ,index, i);

getAllPermutation(a, index+1);

swap(a ,index, i);

public void swap(int[] a, int i, int j) {

int temp = a[i];

a[i] = a[j];

a[j] = temp;

public static void main(String[] args) {

PaiLie robot = new PaiLie();

int[] a = {1,2,3};

robot.runPermutation(a);

2.输出数组a的全排列(可重复取)

如a={1,2}。输出11,12,21,22

如果知道a的length,可以用暴力法求解(n的循环)

如果不知道a的length的情况下:

算法思想:用一个辅助空间b数组存储待输出的排列,用一个参数index记录一个排列的个数

代码清单:

public class PaiLie {

public void runPermutation(int[] a) {

if(null == a || a.length == 0)

return;

int[] b = new int[a.length];--辅助空间,保存待输出排列数

getAllPermutation(a, b, 0);

public void getAllPermutation(int[] a, int[] b, int index)

{

if(index == a.length){

for(int i = 0; i index; i++){

System.out.print(b[i] + " ");

System.out.println();

return;

for(int i = 0; i a.length; i++){

b[index] = a[i];

getAllPermutation(a, b, index+1);

public static void main(String[] args){

PaiLie robot = new PaiLie();

int[] a = {1,2,3};

robot.runPermutation(a);

3.输出数组a的全排列(非递归)

如a={1,2,3}。输出123,132,213,231,312,321

全排列的非递归算法也不唯一,我写一个最常用的按字典序非递归算法

所谓字典序就是按照排列数的从大到小或从小到大输出,如123,132,2.,3.

算法思想:如果能按顺序输出序列是这个算法的核心,为了保证按顺序输出先对数组a进行排序。然后从后向前找到第一个顺序对(12是顺序对,21不是)标记为i,然后再从后面向前找到第一个比i大的数,记录

为j,随后交换i,j对应的值,再逆序数组a[i+1]到a[length-1]。听到这里大家一定很迷糊,我们来举个例子,比如说2431这个数我们先在i,因为31是逆序,43是逆序,24是顺序,所以i=0;接着我们找j,第一个比2大的数是3,所以j=3,然后交换i,j变成(3,4,2,1)我们看看为什么要交换2,3?因为这个算法的核心思想是按字典序,而2431是以2开头的最大排列,下一个数就得是以3开头了(如果原数是2341按算法就是先要变成2431),接着3421这个数要进行i+1到length-1之间的逆序,变成3124,这个是2431的下一个数。所以可以看出交换后的数从下位开始到最后一定是一个逆序排列,所以逆序后才变成了相对的“最小值”。

--代码清单:

import java.util.Arrays;

public class PaiLie {

public void runNoRecursionOfPermutation(int[] a){

Arrays.sort(a);--对数组排序

while(true){

printArray(a);--输出一个排列

int i;--从后向前,记录一对顺序值中的小值下标

int j;--从后向前,记录比i大的第一个数

for(i = a.length-2; i = 0; i--){

if(a[i] a[i+1])--如果找到i跳出

else if(i == 0)--说明是最大逆序数退出函数

相关文档
最新文档