字典序全排列输出下一个的java实现

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);
		}
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值