package edu.pku.ss.hlj;
/**
* 字典序法中,对于数字1、2、3......n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。例如对于5个数字的排列
* 12354和12345,排列12345在前,排列12354在后。按照这样的规定,5个数字的所有的排列中最前面的是12345,最后面的是 54321。
* 字典序算法如下:
* 设P是1~n的一个全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn
* 1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即 j=max{i|pi<pi+1}
* 2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk 3)对换pj,pk 4)再将pj+1......pk-1pkpk+1pn倒转得到排列p
* '=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个排列。
* 例如839647521是数字1~9的一个排列。从它生成下一个排列的步骤如下: 自右至左找出排列中第一个比右边数字小的数字4 839647521
* 在该数字后的数字中找出比4大的数中最小的一个5 839647521 将5与4交换 839657421 将7421倒转 839651247
*
*所以839647521的下一个排列是839651247。
*
* -->易知该算法复杂度为O(N),而如果对其全排列然后选给定序列的下一个的话算法复杂度是O(N^2)
*
* @author Administrator
*
*/
public class Youdao2 {
public static void main(String[] args) {
String str = "839647521";
System.out.println(function(str));
}
public static String function(String str) {
char[] strs = str.toCharArray();
int i = 0;
int j = 0;
int tempMin = 512;
int tempCur = 0;
StringBuffer sb = new StringBuffer(strs.length);
for (i = strs.length - 2; i >= 0; i--) {
if (strs[i] < strs[i + 1]) {
break;
}
}
for (j = i + 1; j < strs.length - 1; j++) {
if (strs[j] > strs[i] && strs[j] < tempMin) {
tempMin = strs[j];
tempCur = j;
}
}
swap(strs, i, tempCur);
reverse(strs, i + 1, strs.length - 1);
for (char c : strs) {
sb.append(c);
}
return sb.toString();
}
public static void swap(char[] ch, int i, int j) {
char temp;
temp = ch[i];
ch[i] = ch[j];
ch[j] = temp;
}
public static void reverse(char[] ch, int i, int j) {
int start = 0;
int end = 0;
for (start = i, end = j; start < end; start++, end--) {
swap(ch, start, end);
}
}
}
字典序全排列输出下一个的java实现
最新推荐文章于 2022-07-04 21:10:17 发布