The code has been divided into 4 functions each one representing a step to find the next lexiccographic permutation of a given string
The mapAll function just iterates over and over computing the next lexicographic permutation until going back to the original string
package Strings;
import java.util.Arrays;
public class StringLexicographicMap {
public static void main(String[] args) {
String input = "ABBCC";
//String result = lexicographicMapNext(input);
//System.out.println(result);
lexicographicMapAll(input);
}
public static void lexicographicMapAll(String s){
String result = s;
do{
result = lexicographicMapNext(result);
System.out.println(result);
}while(result != null);
}
public static String lexicographicMapNext(String s){
char [] init = s.toCharArray();
//1. FIND FIRST
int firstIndex = findFirst(init);
//check if we got an string that is the last in lexicographic order.
//Another way to word it is to say that if we find its next
//we would go back to a perfectly sorted array
if(firstIndex == -1) return null;
char firstElem = init[firstIndex];
//2. FIND CEILING OF FIRST
int ceilingIndex = findCeiling(init, firstIndex);
char ceilingElem = init[ceilingIndex];
//3. SWAP FIRST AND CEILING
init[firstIndex] = ceilingElem;
init[ceilingIndex] = firstElem;
//4. SORT SUBSTRING (ASCENDING) AFTER FIRST CHARACTER
String result = sortAfterFirst(init, firstIndex);
return result;
}
//FIND FIRST FUNCTION
//Finds rightmost character that is smaller than its next character
//---------------------------------------------------------------------
//returns the index of the character that satisfies the above condition
//returns -1 when this condition never happens (e.g ZBA)
public static int findFirst(char[] a){
for(int i = a.length - 2; i >= 0; i--){
char current = a[i];
char currentNext = a[i + 1];
if((int)current < (int) currentNext){
return i;
}
}
return -1;
}
//FIND CEILING FUNCTION
//Finds the smallest character on right of FIRST character
//which is greater than FIRST character
//---------------------------------------------------------------------
//returns the index of the ceiling character
public static int findCeiling(char[] a, int firstIndex){
char first = a[firstIndex];
char smallest = a[firstIndex + 1];
int smallestIndex = firstIndex + 1;
for(int i = firstIndex + 2; i < a.length; i++){
if(a[i] < smallest && a[i] > first){
smallest = a[i];
smallestIndex = i;
}
}
return smallestIndex;
}
//SORT ELEMENTS AFTER INDEX OR FIRST *ORIGINAL* INDEX
//---------------------------------------------------------------------
//returns a string with elements ordered after first ORIGINAL index
public static String sortAfterFirst(char[] a, int firstIndex){
StringBuilder bob = new StringBuilder();
for(char c : a){
bob.append(c);
}
String init = bob.toString();
String toOrder = init.substring(firstIndex+1);
char [] toOrderArr = toOrder.toCharArray();
Arrays.sort(toOrderArr);
StringBuilder bob2 = new StringBuilder();
bob2.append(init.substring(0, firstIndex + 1));
for(char c : toOrderArr){
bob2.append(c);
}
return bob2.toString();
}
}