[续]全排列的非递归实现
2012-08-10 09:04
197 查看
前文提到过全排列的递归实现,这里在简单的介绍下全排列的非递归实现。
以6个数字的全排列为例说明,相当于用1,2,3,4,5,6 构造一个六位数,每一位上取一个数,这样一共有6!中方法。
很显然,这6!个数是有大小的,如果按从小到大排列,示意如下:
1 2 3 4 5 6
1 2 3 4 6 5
1 2 3 5 4 6
…………
6 5 4 3 2 1
显然 , 每个数有唯一后继 ! 如果找到一个数没有后继(6 5 4 3 2 1),则停止。
那么问题的重点在于如何判断是否有后继,以及怎样找到后继 ! 是否有后继很好判断,唯一没有后继的只有654321,它的特点是每位的数字比后面的大!如何找到后继,思路很清楚,即对于一个数,找到一个比它大的、最小的数!
来考虑"926510"这个字符串,我们从后向前找第一双相邻的递增数字,"10"、"52"都是非递增的,"26 "即满足要求,称前一个数字2为替换数,替换数的下标称为替换点,再从后往前找一个比替换数大的最小数(这个数必然存在),0、1都不行,5可以,将5和2交换得到"956210",然后再将替换点后的字符串"6220"颠倒即得到"950226"。同理:比如926540的后继应该是946520,而不是956240。
[/code]
除了上述的找后继实现外,还有一种基于变进制数的实现。这里可以用来作为一个参考。
最后附加利用python中itertool模块求全排列的简短代码。
以6个数字的全排列为例说明,相当于用1,2,3,4,5,6 构造一个六位数,每一位上取一个数,这样一共有6!中方法。
很显然,这6!个数是有大小的,如果按从小到大排列,示意如下:
1 2 3 4 5 6
1 2 3 4 6 5
1 2 3 5 4 6
…………
6 5 4 3 2 1
显然 , 每个数有唯一后继 ! 如果找到一个数没有后继(6 5 4 3 2 1),则停止。
那么问题的重点在于如何判断是否有后继,以及怎样找到后继 ! 是否有后继很好判断,唯一没有后继的只有654321,它的特点是每位的数字比后面的大!如何找到后继,思路很清楚,即对于一个数,找到一个比它大的、最小的数!
来考虑"926510"这个字符串,我们从后向前找第一双相邻的递增数字,"10"、"52"都是非递增的,"26 "即满足要求,称前一个数字2为替换数,替换数的下标称为替换点,再从后往前找一个比替换数大的最小数(这个数必然存在),0、1都不行,5可以,将5和2交换得到"956210",然后再将替换点后的字符串"6220"颠倒即得到"950226"。同理:比如926540的后继应该是946520,而不是956240。
[code] public class NonRecursivePermutation {
static int[] arr = new int[] { 1, 2, 3, 4, 5, 6};
static int count = 1;
// 反转区间
private static void reverse(int[] arr, int pBegin, int pEnd) {
while (pBegin < pEnd)
swap(arr, pBegin++, pEnd--);
}
private static void swap(int[] arr, int i, int j) {
int temp;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
private static boolean hasNext() {
for (int i = arr.length - 1; i > 0; i--) {
if (arr[i] > arr[i - 1])
return true;
}
return false;
}
private static void next() {
int len = arr.length;
int replace = 0; // 需替换数
int firstR = 0; // 从后向前找比替换数大的第一个数
// 找降序的相邻2数,前一个数即需替换数
for (int i = len - 1; i > 0; i--) {
if (arr[i] > arr[i - 1]) {
replace = i - 1;
break;
}
}
//System.out.println("需替换数位置:" + replace);
// 从后向前找比替换数大的第一个数
// 比如926540的后继应该是946520,而不是956240
for (int i = len - 1; i > replace; i--) {
if (arr[i] > arr[replace]) {
firstR = i;
break; //找到之后直接退出
}
}
//System.out.println("替换数位置:" + firstR);
// replace与firstR交换
swap(arr, replace, firstR);
// 替换数后的数全部反转
reverse(arr, replace + 1, len - 1);
count++;
print();
}
private static void print() {
for (int i = 0; i < arr.length; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
/**
* @param args
*/
public static void main(String[] args) {
while (hasNext() == true) {
next();
}
System.out.println("数组完全反转后的结果:");
reverse(arr, 0, arr.length - 1);
print();
System.out.println("全排列的数目为:" + count);
/*********************/
System.out.println("数组是否存在后继:" + hasNext());
System.out.println("数组一次替换后的结果:");
next();
}
}
[/code]
除了上述的找后继实现外,还有一种基于变进制数的实现。这里可以用来作为一个参考。
最后附加利用python中itertool模块求全排列的简短代码。
import itertools list(itertools.permutations([1,2,3]))
相关文章推荐
- 递归实现全排列
- 递归实例——C语言实现全排列
- 全排列——递归实现
- 全排列的非递归实现及递归实现
- n个整数全排列的递归实现(C++)
- 全排列的递归实现算法
- 全排列的递归实现
- Ackerman函数的递归、全排列的递归实现、整数划分的递归、二分搜索的递归、合并排序的递归、.快速排序
- 全排列的递归实现方法
- 递归实现 全排列
- 递归实现n个不同字符的所有全排列
- 递归实现全排列
- 全排列实现(递归实现深度优先搜索)
- 全排列的递归与非递归算法实现
- 递归实现全排列,字典序法实现全排列
- python 利用递归实现全排列
- 用递归的方法实现全排列
- 递归实现全排列
- 求模(非递归)全排列算法——Javascript实现
- 递归实现全排列,关于凑算式实例