排列生成算法实现java

33 篇文章 0 订阅
排列生成算法是常用的算法之一,详细的介绍请查考《组合数学》教材。

1.序数法

序数思想来源于数字的表示形式

对于任何给定小于10的m次方的正整数N,我们可以表示为如下形式:

N= a0×10^0+...+a(m-1)×10^(m-1)

也就是说N可以唯一的表示为(a0,..., a(m-1))

同理对于任何属于0~(n!-1)的正整数m 我们可以唯一的表示为

m=a(n-1)*(n-1)!+...+a1*1!

这样给定整数m我们可以唯一的表示为(a(n-1),...,a1)

对于以上的计算,显而易见了。

对于任何一个排列p1,p2,p3,...,pn

ai可以看作是排列p中i+1所在的位置比较i+1小的数的个数。

例如:4213,4右边的比4小的数为3,则a3=3,同理可得

p=(4212)可以表示为(301)

反过来我们可以通过301得到4213。

具体参照《组合数学》

由此可以对于数序算法的核心主要包括两个

一是如何把一个整数映射到一个元素序数

二是对序数的解码

对于算法的实现,如下:

package recursive;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Perm {

	public ArrayList ordinalPerm(String input) {
		int lenght = input.length();
		int num = caculatePerm(lenght);
		ArrayList al = new ArrayList();
		for (int i = 0; i < num; i++) {
			String code = num2ordinal(i, lenght - 1);
			al.add(decode(code, input));
		}
		return al;
	}

	// decode
	private String decode(String code, String input) {
		int[] tag = new int[code.length() + 1];
		char[] content = new char[code.length() + 1];
		for (int i = 0; i < code.length(); i++) {
			int pos = Integer.parseInt(code.charAt(i) + "");
			char temp = input.charAt(input.length() - 1 - i);
			int ept = 0;
			int index = 0;
			// locate the position of new character
			// count the empty slot
			for (int j = tag.length - 1; j >= 0; j--) {
				if (ept == pos && tag[j] != 1) {
					index = j;
					break;
				} else {
					if (tag[j] != 1)
						ept++;
				}
			}
			content[index] = temp;
			tag[index] = 1;

		}
		for (int i = 0; i < tag.length; i++) {
			if (tag[i] == 0)
				content[i] = input.charAt(0);
		}
		String result = "";
		for (int i = 0; i < content.length; i++) {
			result += content[i];
		}
		return result;
	}

	private String num2ordinal(int k, int lenght) {
		String s = "";
		for (int i = 0; i < lenght; i++) {
			s = k % (i + 2) + s;
			k = k / (i + 2);
		}
		return s;
	}

	// the num of permutation
	private int caculatePerm(int n) {
		if (n <= 1) {
			return 1;
		} else {
			int perm = 1;
			for (int i = n; i >= 1; i--) {
				perm *= i;
			}
			return perm;
		}
	}

}
input:1234
output:如下
0	000	1234
1	001	2134
2	010	1324
3	011	2314
4	020	3124
5	021	3214
6	100	1243
7	101	2143
8	110	1342
9	111	2341
10	120	3142
11	121	3241
12	200	1423
13	201	2413
14	210	1432
15	211	2431
16	220	3412
17	221	3421
18	300	4123
19	301	4213
20	310	4132
21	311	4231
22	320	4312
23	321	4321





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值