转自:http://www.cnblogs.com/dragonpig/archive/2010/01/21/1653680.html

   http://www.notesandreviews.com/programming/algorithm-to-generate-permutations-explained

1. 字典序列

这个方法的思路在于按照从“小到大”的方式生成所有排列。假设每一个参与排列的项都是可以比较大小的,即使不很直观也总可以找到某种映射法(随便赋个数),字典序就是最左的位权重最高,向右依次比较大小。

1. 算法的初始步骤为,排成最小的序列。a1<a2<...<an (为了方便打字 假设每项唯一)

2. 然后从右向左,找到第一个 aj<aj+1,意味着aj+1>aj+2>...>an

3. 在[aj+1到an]中找到最小的ak并且aj<ak ,交换aj和ak

4. 镜像反转[aj+1到an]的元素,重复第二步直到序列最大,a1>a2>...>an

Example generating all of the permutations of 12345:

The first permutation is 12345 itself.  Taking that and running through the steps described above, we can generate the next permutation 12354.  Here’s how:

Step 1: Referring to step 1 above, we first need to find item list[i]. Going backwards through the list, the first number we come to that is less than the number to the right of it is 4 (4 is less than the number 5 which is to the right of it). Let’s keep a note of that by drawing a ring around the 4 and labelling its position i.

Step 2: Referring to step 2 above, we now need to find list[j]. Going backwards through the list, the first number we come to that is greater than the number we just circled in step 1 is the 5. Let’s keep a note of that by drawing a ring around the 5 and labelling its position j.

Step 3: Swapping the items at i and j, we now get 12354. (We have swapped the numbers at i and j but i and j themselves don’t move so now i points to 5 and j points to 4.

Step 4: In this step, we need to reverse the items from i+1, which is the 4 to the end of the list. Since 4 is already at the end of the list, there is nothing to do here. So the next permutation is 12354.

How to generate the next permutation

Taking 12354 and running through the steps again, we get 12435.

How to generate the next permutation

Continuing on would give the next permutation, and then the next and so on until the result is 54321.

2. backtracking

相当直观好懂的算法,直接给出实现

[a1,a2 ... aN]

generate(int N)
 { 
      if (N == 1) dosomething();
      for (int i = 1; i <= N; i++)
      { swap(i, N); generate(N-1); swap(i, N); }
 }

假设generate(N-1)能产生所有排列,那么通过和之前N-1个元素交换最后的第N个元素(或者不交换)可以产生新的排列,所产生的个数正好是N×generate(N-1),满足排列定义,所以是N!个。算法中的后一个swap是为了保证把最后一个元素换回原来位子,还原整个序列,注意所有递归操作施加在了同一个静态数组上。

3. Plain changes

或者叫做 Johnson-Trotter 算法。令人佩服的是这个算法可以追溯到17世纪的英国。当时的教堂有很多编钟,为了每次摆出不同的花样(为了my lord),需要对钟的排列作出调整。古人不容易啊要想算出5个钟120种变化已经很不容易了,而且更令人抓狂的是,这些编钟各个体形巨大、笨重,所以需要一种每次移动最少的方法。至理名言,最优秀的程序员是因为太懒了,为了“偷懒”ringers找到了好办法,后来被形式化成这个算法了(这里有相关历史介绍)

设[a1,a2 ... aN] 每一项都有向左或向右两个移动方向。

1.初始化所有移动方向向左

2.如果移动方向的值比自己小,就可移动,比如 <1 >2 <3, 3可以移动,2不可以因为3大

3.移动最大的可以动项

4.将所有比移动项大的项方向反转 重复第三步 直到不能移动为止

举个N=4的例子:

<1  <2  <3  <4
<1 <2 <4 <3
<1 <4 <2 <3
<4 <1 <2 <3
4> <1 <3 <2
<1 4> <3 <2
<1 <3 4> <2
<1 <3 <2 4>
<3 <1 <2 <4
<3 <1 <4 <2
<3 <4 <1 <2
<4 <3 <1 <2
4> 3> <2 <1
3> 4> <2 <1
3> <2 4> <1
3> <2 <1 4>
<2 3> <1 <4
<2 3> <4 <1
<2 <4 3> <1
<4 <2 3> <1
4> <2 <1 3>
<2 4> <1 3>
<2 <1 4> 3>
<2 <1 3> 4>

4. Heap's algorithm

是对backtracking的改进,减少了第一次swap,效率渴望翻倍

[a1,a2 ... aN]

generate(int N)
 { 
      if (N == 1) dosomething();
      for (int i = 1; i <= N; i++)
      { generate(N-1); swap(N % 2 ? 1 : i, N); }
 }

如果下标从零开始swap改为N % 2 ? i : 0或者N % 2 * i

该算法和index table有关,而这个方法又牵涉到cycle index是和group theory有关的东西了。

(转)排列算法 Permutation Generation的更多相关文章

  1. 排列算法汇总(下一个排列,全排列,第K个排列)

    一.下一个排列 首先,STL提供了两个用来计算排列组合关系的算法,分别是next_permutation和prev_permutation. next_permutation(nums.begin() ...

  2. 排列(permutation) 用1,2,3,…,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要 求abc:def:ghi=1:2:3。按照“abc def ghi”的格式输出所有解,每行一个解。

    #include <stdio.h> #include <math.h> // 算法竞赛的目标是编程对任意输入均得到正确的结果. // 请先独立完成,如果有困难可以翻阅本书代码 ...

  3. Java字符串排列算法

    Java字符串排列算法 题目:现有ABCDE 5个球 构成的排列组合 可重复抽取 最多取到16个 共有多少种组合方式? 比如:取1个球可以构成的组合有 A B C D E 共5种,取2个球可以构成的组 ...

  4. 算法竞赛入门经典 习题 2-10 排列(permutation)

    习题 2-10 用1,2,3.....,9组成3个三位数abc.def和ghi,每一个数字恰好使用一次,要求abc:def:ghi=1:2:3.输出全部解. #include <stdio.h& ...

  5. [Swift]LeetCode31. 下一个排列 | Next Permutation

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  6. 31、下一个排列 | 算法(leetode,附思维导图 + 全部解法)300题

    零 标题:算法(leetode,附思维导图 + 全部解法)300题之(31)下一个排列 一 题目描述 二 解法总览(思维导图) 三 全部解法 1 方案1 1)代码: // 方案1 "双指针法 ...

  7. PHP数组内容不重复组合排列算法

    最近在做ecshop的商品库存模块,分别给一款商品的多个属性组合设置库存,如下图: 一款手机有不同颜色,屏幕尺寸,系统和电量,都要设置不同的库存,如果都要手动选择属性组合,则会耗费很多不必要的时间.假 ...

  8. 横向图片墙排列算法及demo

    演示地址: http://codeman35.itongyin.com:19005/v1/9gg_v2.html 功能: 按照不同的图片比例,进行横向9宫格排列,原则是尽量排列的整齐,不要多余出来格子 ...

  9. C++ 递归位置排列算法及其应用

    废话不多说,我们先看一下位置排序的算法: #include <iostream> using namespace std; int n = 0; int m = 2; int l = 0; ...

随机推荐

  1. javascripy的innerHTML在IE8下的异常

    使用jQuery的datatable插件的时候发现,IE8下显示异常,仔细调查一番,发现是浏览器对innerHTML的差异导致的. 实例代码: var nTd = document.createEle ...

  2. libevent 信号示例

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  3. Layout Support 获取上下bar的长度

    Layout Support This protocol . You can use layout guides as layout items in the NSLayoutConstraint f ...

  4. Oracle之sql追踪

    select * from v$sqlarea t where t.sql_text like '%_070%' order by t.LAST_ACTIVE_TIME desc SELECT * F ...

  5. Qt中的事件

    1. 引自---http://blog.sina.com.cn/s/blog_6e80f1390100pro4.html 信号和事件的区别就在与,事件比信号更加底层,而且如果一个信号对应多个槽的话,信 ...

  6. oracle增加表空间的四种方法,查询表空间使用情况

    增加表空间大小的四种方法Meathod1:给表空间增加数据文件ALTER TABLESPACE app_data ADD DATAFILE'D:\ORACLE\PRODUCT\10.2.0\ORADA ...

  7. 软件工程随堂小作业——随机四则运算(C++)

    一.设计思路: 1.程序的主体部分是循环输出,次数即题目数目由用户输入: 2.三个整型变量+rand函数来实现随机数四则运算,一个变量代表加减乘除,另外两个用作运算数: 3.用户体验:题目分三列,排列 ...

  8. Netsharp快速入门(之4) 基础档案(之C 实体建模 计量单位、商品、往来单位)

    作者:秋时 杨昶   时间:2014-02-15  转载须说明出处 3.3.2   基础档案建模 1.在基础档案项目,右击,选择新建包, 2.录入包的名称,录入名称.完成后点确定 3.3.2.1 计量 ...

  9. python 数据结构-字典

    原文地址:http://docs.pythontab.com/python/python3.4/datastructures.html#tut-tuples 理解字典的最佳方式是把它看做无序的键: 值 ...

  10. bnuoj 34985 Elegant String DP+矩阵快速幂

    题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=34985 We define a kind of strings as elegant s ...