字典序算法
字典序
就是按照字典中出现的先后顺序进行排序
- 单个字符
在计算机中,25个字母以及数字字符,字典排序如下:
字母 : ABCDE~XYZ
数字:12345678~ - 多个字符
两个字符串比较大小,是按照从左到右的顺序进行比较,如果第1位相等,就比较第2位,直至有一位可以比较出大小来,则不再继续比较。 - 全排列的字典
给定多个字符或者字符,可以按照任意顺序进行排列,所有排列称为全排列。
每一种排列对应一个字符串,如果这些字符串按照字符串大小的顺序进行排序,那么就这种排序是基于字典序的全排列。
字典序算法
解决问题 : 给定其中一种排列,求基于字典序的下一种排列(求全排列的下一个数)。
eg: 给出 1,2,3,4,5,6 这6个数。 求 组成的任意一个整数A 的全排列下一个数。(通俗点:求一个包含这6个数的 整数,要求 大于且仅大于原数 A)
例如 :
123456-》 123465
123546-》123564
124356-》124365
654321=》由于是排列中的最大数,所以没有下一个排列。
综上,为了接近原数,我们 要尽量 保持高位不变,低位在最小范围内变换顺序。
至于变换顺序的范围,则取决于当前整数的逆序区。
获取 全排列下一个数的步骤:
/**
* 获取全排列的下一个数
* @return
*/
public static int[] findNextPermutation(int[] array){
int[] datas = Arrays.copyOf(array, array.length);
//1.找出逆序区域的边界索引(逆序遍历)
int startIndex=0;
for (int i = datas.length - 1; i > 0; i--) {
if(datas[i]>datas[i-1]){
startIndex=i;
break;
}
}
//如果逆序区起始索引为0,说明已经是最大排列,没有下一个数
if(startIndex==0){
return null;
}
//2.遍历逆序区,交换逆序区前一个数 和逆序区中比他大的最小值。
//逆序区前一个数
int beforeData=datas[startIndex-1];
for (int i = datas.length - 1; i >= startIndex; i--) {
if(datas[i] >beforeData){
//交换位置
datas[startIndex-1]=datas[i];
datas[i]=beforeData;
break;
}
}
//逆序区重新排序(由于有序区已经是从大到小的有序序列,所以只要交换首位对应位置即可 转换成正序)
for (int i=startIndex,j=datas.length-1;i<j;i++,j--){
int temp=datas[i];
datas[i]=datas[j];
datas[j]=temp;
}
return datas;
}