转自: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. Java入门到精通——调错篇之解决MyEclipse 输入注册码后:Enter or update your subscription information.问题

    这几天,我用MyEclipse做例子的时候总是出现下面图上面的提示: 不用看就是注册码到期了要注册.找了好几个注册码总是出现Enter or update your subscription info ...

  2. bzoj 1012 [JSOI2008]最大数maxnumber

    原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1012 线段树,单点更新.. #include<algorithm> #incl ...

  3. android开发系列之回调函数

    想必对于回调函数大家肯定不陌生,因为这是我们开发里面常用的代码技巧.我也就不废话了,让我们直接来看代码吧! public class TestCallback { public interface I ...

  4. Hadoop和大数据:60款顶级大数据开源工具

    一.Hadoop相关工具 1. Hadoop Apache的Hadoop项目已几乎与大数据划上了等号.它不断壮大起来,已成为一个完整的生态系统,众多开源工具面向高度扩展的分布式计算. 支持的操作系统: ...

  5. Objective-C编码规范

    参考 http://www.csdn.net/article/2015-06-01/2824818-objective-c-style-guide/1 介绍 我们制定Objective-C编码规范的原 ...

  6. shell 编程基础

    1 创建shell脚本文件 要创建一个shell脚本文件,必须在第一行指定要使用的shell,其格式为: #! /bin/bash 接着加上该shell文件的注释,说明该脚本文件用来干什么,有谁创建, ...

  7. linux 简单的DMA例程

    一个简单的使用DMA 例子 示例:下面是一个简单的使用DMA进行传输的驱动程序,它是一个假想的设备,只列出DMA相关的部分来说明驱动程序中如何使用DMA的. 函数dad_transfer是设置DMA对 ...

  8. python ndentationError: unexpected indent

    python 缩进搞了好久,每次都自己看了没什么问题 IndentationError: unexpected indent 每次都是这个错误. 后来查资料是vimrc配置有点问题 我在写代码的时候用 ...

  9. SDOI2016 round1滚粗记

    Day -1 刚刚从HN集训回来,感觉整个人萌萌哒.考前不断立flag——这次我一定会滚粗的,然后设想着滚粗之后文化课先补什么,浑浑噩噩的过了一天,晚上看到CA爷(娘)发了关于cena爆栈的问题,这时 ...

  10. NET Core中使用Redis

    NET Core中使用Redis 注:本文提到的代码示例下载地址> https://code.msdn.microsoft.com/How-to-use-Redis-in-ASPNET-0d82 ...