全排列问题问题的两种算法--递归与字典序
2013-04-21 10:48
267 查看
本文描述全排列问题的递归算法与排序算法。
再求得以{1}开头的排列之后,可以依次求解分别以{2},{3},{4}开头的排列。可参考下图求解
Java代码参考:
求解下一个排列的算法如下:
对于给定的数组a,从后往前扫描数组,找到位置i满足a[i]>a[i-1],记录位置i-1为j。然后再次从后往前扫描数组a,找到位置k满足a[k]>a[j]。交换a[j]与a[k]并逆序a[i...n)。对于排列 1 2 4 3的下一个排列1 3 2 4的求解如下图所示:
Java参考代码如下:
c++的stl库中有函数next_permutation()可以生成下一个排列。
对于给定序列 1 2 3 3,使用字典序方法生成的全排列如下:
参考资料:
全排列的算法思想和实现
全排列
全排列算法及实现
全排列的六种算法
递归算法
递归算法的原理是,对于给定的集合{1, 2, 3, 4},首先以{1}作为开头,求解集合{ 2, 3, 4}的排列。求解集合{2, 3, 4}的排列时,首先以{2}作为开头,求解集合{3, 4}的排列。求解集合{3, 4}的排列时,先求解以{3}开头的排列,然后求解以{4}开头的排列。至此可以求得排列1 2 3 4和1 2 4 3。以此回朔便可求得以{1}开头的六个排列。再求得以{1}开头的排列之后,可以依次求解分别以{2},{3},{4}开头的排列。可参考下图求解
Java代码参考:
static void swap(int[] a, int i, int j) { if (i != j) { int t = a[j]; a[j] = a[i]; a[i] = t; } } static void permutation(int[] a, int start, int end) { if (start >= end) { for (int i = 0; i < end; i++) { System.out.printf("%d ", a[i]); } System.out.printf("\n"); return; } for (int i = start; i < end; i++) { swap(a, i, start); // 交换元素,使得每一个元素都有放在第一位的机会。 permutation(a, start + 1, end); // 递归调用 swap(a, i, start); // 恢复原始的list,不影响下次递归调用。 } }
字典序算法
字典序算法使用字典序的思想来计算排列。具体来说,对于给定的一个排列,计算该排列是否具有下一个排列,如果存在则将下一个排列计算出来。例如,对于排列 1 2 3 4,下一个排列将是 1 2 4 3,这个排列是比 1 2 3 4大的排列中最小的一个。然而,对于排列 4 3 2 1来说就没有下一个排列了,因为该排列本身是所有排列中最大的一个。全排列的排序算法可以生成去除重复的所有排列,但是要求解所有排列时,必须先求出最小的排列,即该算法需要对集合先进行排序。求解下一个排列的算法如下:
对于给定的数组a,从后往前扫描数组,找到位置i满足a[i]>a[i-1],记录位置i-1为j。然后再次从后往前扫描数组a,找到位置k满足a[k]>a[j]。交换a[j]与a[k]并逆序a[i...n)。对于排列 1 2 4 3的下一个排列1 3 2 4的求解如下图所示:
Java参考代码如下:
static boolean next_permutation(int list[]) { int i, k; int n = list.length; // 步骤1:得到i。 for (i = n - 1; i > 0; i--) { if (list[i] > list[i - 1]) { break; // 记下下标i。 } } // 表示当前排列已经是字典序中的最后一个序列,没有下一个了。 if (i <= 0) { return false; } // 步骤2:得到k。 for (k = n - 1; k > 0; k--) { if (list[k] > list[i - 1]) { break; // 记下下标j。 } } // 步骤3:互换list[i-1]和list[j]。 int temp = list[i - 1]; list[i - 1] = list[k]; list[k] = temp; // 步骤4:逆置list[i...n]。 int start, end; for (start = i, end = n - 1; start < end; start++, end--) { temp = list[start]; list[start] = list[end]; list[end] = temp; } return true; }
c++的stl库中有函数next_permutation()可以生成下一个排列。
对于给定序列 1 2 3 3,使用字典序方法生成的全排列如下:
1 2 3 3 1 3 2 3 1 3 3 2 2 1 3 3 2 3 1 3 2 3 3 1 3 1 2 3 3 1 3 2 3 2 1 3 3 2 3 1 3 3 1 2 3 3 2 1
参考资料:
全排列的算法思想和实现
全排列
全排列算法及实现
全排列的六种算法
相关文章推荐
- 算法笔记——【递归】全排列问题
- 排列的字典序问题 算法与设计
- 【算法设计与分析】递归与分治----2.4 排列问题
- 数组排序问题的两种方法:插入排序算法和递归(分治)算法
- 全排列问题算法分析与实现(递归、非递归)
- 第二章 递归与分治策略(排列的字典序问题)
- 全排列算法递归及STL实现,八皇后问题
- 0002算法笔记——【递归】排列问题,整数划分问题,Hanoi问题
- (排列生成算法)枚举排列的两种方法:递归枚举和next_permutation (使用多用next_permutation)
- 全排列问题算法实现--递归
- 0002算法笔记——【递归】排列问题,整数划分问题,Hanoi问题
- 书上算法排列问题
- 递归--【全排列问题】九度1459.Prime ring problem
- 喝汽水问题的两种算法实现
- 递归求全排列问题学习
- 求子集问题算法分析与实现(递归、非递归)
- 算法训练_求先序排列 【使用递归】
- 常用算法的递归实现问题分析(针对《数据结构与程序设计》by Robert.L.Kruse)
- 漫谈二叉树之递归遍历算法(两种不同的思路)
- 第一篇:算法之使用递归求解迷宫问题