(转)排列算法 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; ...
随机推荐
- [php]如何更改wamp默认的mysq空密码?
最近刚开始学php,爬坑中.上午看了会儿书,下了个源码,把文件部署到www下之后,也导入了sql文件,但是进入之后显示 = = 一开始不知道是什么.后来百度之后发现是mysql的问题,应该是源码中p ...
- windows下python+flask环境配置详细图文教程
本帖是本人在安装配置python和flask环境时所用到的资源下载及相关的教程进行了整理罗列,来方便后面的人员,省去搜索的时间.如果你在安装配置是存在问题可留言给我. 首先罗列一下python+fla ...
- Orcle 系统表
oracle系统表大全 一.管理员 1.用户: select username from dba_users; 改口令 alter user spgroup identified by spgtest ...
- "Programming"和"Programming"是同一个"Programming"吗?
什么意思? C语言没有专门的字符串类型,但是,它同样可以处理字符串.本文不是讨论字符串的使用,而是讨论C字符串之间的关系.如题,在C语言代码中,如果定义#define STR = "Prog ...
- C# Hadoop学习笔记
记录一下学习地址 http://www.360doc.com/content/14/0607/22/3218170_384675141.shtml
- [Linq Expression]练习自己写绑定
源代码:TypeMapper.zip 背景 项目中,我们会经常用到各种赋值语句,比如把模型的属性赋值给UI,把视图模型的属性拷贝给Entity.如果模型属性太多,赋值也会变成苦力活.所以,框架编程的思 ...
- verilog中级别到底是什么?级别的分类是什么???
1.级别到底是什么? 答:所谓的系统级,算法级,RTL级,门级,开关级,就是在不同的层次上来描述某个电路模块.当然行为级和结构级就是在行为上和结构上来描述电路模块. 模块可以用不同级别语言来描述,当然 ...
- 【转载】matlab中freqz函数的使用
freqz函数计算线性系统的频率响应,包括幅频响应和相频响应,基本输入为线性系统的AMMA模型系数向量,一个典型的AMMA模型为 % jw -j ...
- 格式化输出[part1/标准控制符]
/* 设置输出字符的宽度 width(int)是iostream类的成员函数,可以通过cout对象来调用,即cout.width(int) 注: 1.width(int)只影响将要显示的一个对象,之后 ...
- Java团队项目总结
Java团队项目总结 1.项目实现情况 项目概述: 我们团队项目准备实现一个有关于大富翁有的游戏程序. 大富翁游戏,以经营权为主要的游戏方式,通过购买经营权与架构经营的星级服务来获得最大的利益,当其他 ...