(转)排列算法 Permutation Generation
转自: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的更多相关文章
- 排列算法汇总(下一个排列,全排列,第K个排列)
一.下一个排列 首先,STL提供了两个用来计算排列组合关系的算法,分别是next_permutation和prev_permutation. next_permutation(nums.begin() ...
- 排列(permutation) 用1,2,3,…,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要 求abc:def:ghi=1:2:3。按照“abc def ghi”的格式输出所有解,每行一个解。
#include <stdio.h> #include <math.h> // 算法竞赛的目标是编程对任意输入均得到正确的结果. // 请先独立完成,如果有困难可以翻阅本书代码 ...
- Java字符串排列算法
Java字符串排列算法 题目:现有ABCDE 5个球 构成的排列组合 可重复抽取 最多取到16个 共有多少种组合方式? 比如:取1个球可以构成的组合有 A B C D E 共5种,取2个球可以构成的组 ...
- 算法竞赛入门经典 习题 2-10 排列(permutation)
习题 2-10 用1,2,3.....,9组成3个三位数abc.def和ghi,每一个数字恰好使用一次,要求abc:def:ghi=1:2:3.输出全部解. #include <stdio.h& ...
- [Swift]LeetCode31. 下一个排列 | Next Permutation
Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...
- 31、下一个排列 | 算法(leetode,附思维导图 + 全部解法)300题
零 标题:算法(leetode,附思维导图 + 全部解法)300题之(31)下一个排列 一 题目描述 二 解法总览(思维导图) 三 全部解法 1 方案1 1)代码: // 方案1 "双指针法 ...
- PHP数组内容不重复组合排列算法
最近在做ecshop的商品库存模块,分别给一款商品的多个属性组合设置库存,如下图: 一款手机有不同颜色,屏幕尺寸,系统和电量,都要设置不同的库存,如果都要手动选择属性组合,则会耗费很多不必要的时间.假 ...
- 横向图片墙排列算法及demo
演示地址: http://codeman35.itongyin.com:19005/v1/9gg_v2.html 功能: 按照不同的图片比例,进行横向9宫格排列,原则是尽量排列的整齐,不要多余出来格子 ...
- C++ 递归位置排列算法及其应用
废话不多说,我们先看一下位置排序的算法: #include <iostream> using namespace std; int n = 0; int m = 2; int l = 0; ...
随机推荐
- 关于HTML中,绝对定位,相对定位的理解...(学习HTML过程中的小记录)
关于HTML中,绝对定位,相对定位的理解...(学习HTML过程中的小记录) 作者:王可利(Star·星星) HTML中 相对定位:position:relative; 绝对定位:position ...
- iOS开发之Pch预编译文件的创建
在Xcode6之前,创建一个新工程xcode会在Supporting files文件夹下面自动创建一个“工程名-Prefix.pch”文件,也是一个头文件,pch头文件的内容能被项目中的其他所有源文件 ...
- 在 App 扩展和主 App 间共享数据
tags: iOS 8,Swift,App Groups 随着 iOS 8 的发布,苹果为广大开发者很多新的 API,其中最突出显著的就非 App Extension 莫属了.这为开发者们又带来了很多 ...
- HMMPfam的安装使用手记(转载)
转载至:http://blog.sina.com.cn/s/blog_3f6403290100rb61.html(感谢原文作者) HMMPfam的安装使用手记前言 简要介绍一下 HMMPfam吧.这还 ...
- 关于VS2010error RC2170 : bitmap file res\tmp1.bmp is not in 3.00 format
我们有时候向VS中的程序插入图片,会出现如下错误: 这是VS的一个bug,对于不能识别的资源,添加的时候,VS会弹出一个对话框让你填类型,这个类型其实是字符串表示,而不是像内置类型,例如整数. 解 ...
- 转载:SQL索引一步到位
原文: http://www.cnblogs.com/AK2012/archive/2013/01/04/2844283.html SQL索引一步到位(此文章为“数据库性能优化二:数据库表优化”附属文 ...
- Daily Scrum6
今天我们小组开会内容分为以下部分: part 1: Anti-spam and anti-abuse module模块总结: part 2: 部分优化代码的展示于交流: part 3:针对用户积分模块 ...
- MFC源码不能设置断点调试
用VS2013中MFC开发应用程序时,进入MFC源码设置断点调试.但是在调试过程中发现无法进入源码.最后发现在MFC设置的MFC的使用默认值是在共享dll中使用MFC,这就意味着MFC中的源码并没有连 ...
- git简单入门
git简单入门 标签(空格分隔): git git是作为程序员必备的技能.在这里就不去介绍版本控制和git产生的历史了. 首先看看常用的git命令: git init git add git comm ...
- CRT团队组员博客地址统计
CRT团队GitHub地址:https://github.com/CoffeeRobotTeam/Coffee-Robot-System 洪超 http://www.cnblogs.com/chaoh ...