本文已参与「新人创作礼」活动,一起开启掘金创作之路。
一、字典序概述
字典序是一种排序算法。顾名思义,就是按照字典中的英文字母的先后顺序来排序。 比如有两个字符串,我们按字符串中每个字符在字典中的排序顺序排序时,这就是字典序:
aac
aad
abf
bdf
bhz
...
当第一个字符相等时,比较第二个字符,对于数字也是相同。
二、下一个全排列问题
字典序是一种排序算法,经典应用之一是求下一个全排列问题。 什么是全排列?可以看leetcode上的题目:46.全排列
下一个全排列指的是对于当前字符串,下一个比它大的(字典序)排列。比如(123),按字典序,下一个比他大的排列是:(132) (213) (231) (312) (321);
*这里说明一下,当给出123时,求其全排列,其实就相当于46.全排列但是给213时,就不是46.全排列
为什么呢?
因为46.全排列时,不管给出什么,都需要列出所有的排列,而下一个全排列问题,不会列出所有,因为其是按字典序进行的,当给出的是213时,213前面的123、132不会出现。
下面给出算法思路:
- 对于排列a[1...n],找到所有满足a[k]<ak+1的k的最大值,如果这样的k不存在,则说明当前排列已经是a的所有排列中字典序最大者,所有排列输出完毕。
- 在a[k+1...n]中,寻找满足这样条件的元素l,使得在所有a[l]>a[k]的元素中,a[l]取得最小值。也就是说a[l]>a[k],但是小于所有其他大于a[k]的元素。
- 交换a[l]与a[k].
- 对于a[k+1...n],反转该区间内元素的顺序。也就是说a[k+1]与a[n]交换,a[k+2]与a[n-1]交换,……,这样就得到了a[1...n]在字典序中的下一个排列。
下面给出代码实现:
//是否可以找到下一个全排列
public bool findNext(string str){
int num = str.length();
int i, j;
StringBuilder sb = new StringBuilder(str);
//1、从右向左,找到第一个左边小于右边的数,如54231,则找到2
for(i=num-2; i>=0; i--) {
if(str.charAt(i) < str.charAt(i + 1)) {
break;
}
}
//如果没有找到,说明已经最大
if(i<0){
return false;
}
//2、从右向左,找到第一个大于str[i]的元素,如54231,则找到3
for(j=num-1; j>i; j--){
if(str.charAt(i) > str.charAt(i + 1)){
break;
}
}
//3、交换i、j位置字符,如54321,交换完成后是54312
int temp = str.charAt(i);
sb.charAt(i) = str.charAt(j);
sb.charAt(j)= temp;
//4、对i之后的元素进行排序,排序完成后为54123。(反转也行)
Arrays.sort(cahr[]数组,i + 1, num); //这里不再赘述字符串与数组间转换
return true;
}
参考资料: 1、www.cnblogs.com/nowornever-…