/* File: Permutations.java * Created: 10/1/2018 * Author: Sabbir Manandhar * * Copyright (c) 2018 Hogwart Inc. */ import java.util.*; //======================================================================================= /** * @author Sabbir Manandhar manandharsabbir@gmail.com * @version 1.0 */ public class Permutations { public static void main(String[] args) { List<String> permutations = permutationWithoutDuplicates("ABCD"); for (String permutation : permutations) System.out.println(permutation); System.out.println(); permutations = permuteWithDuplicates("AAABB"); for (String permutation : permutations) System.out.println(permutation); } // main //------------------------------------------------------------------------------------- //------ Solution 1: For Input with Unique Characters Only ----------- /** * Computes permutation of given string without any duplicate characters. * For string duplicate character, results will contain duplicate entries. * @param s input string * @return List of permutations */ public static List<String> permutationWithoutDuplicates(String s) { char[] chars = s.toCharArray(); List<String> permutations = new ArrayList<>(); permutationWithoutDuplicatesHelper(chars, 0, permutations); return permutations; } // permutationWithoutDuplicates //------------------------------------------------------------------------------------- /** * Recursive helper method to compute permutations of a character array without duplicates. * @param chars input character array * @param cursor pointer to current location considered. Characters before this pointer and kept fixed. * @param permutations List holding resulting permutations */ private static void permutationWithoutDuplicatesHelper(char[] chars, int cursor, List<String> permutations) { if (cursor == chars.length) { permutations.add(new String(chars)); return; } for (int i = cursor; i < chars.length; i++) { swap(chars, cursor, i); // keep the selected character fixed and compute permutations of remaining characters permutationWithoutDuplicatesHelper(chars, cursor + 1, permutations); swap(chars, cursor, i); } } // permutationWithoutDuplicatesHelper //------------------------------------------------------------------------------------- /** * Utility method to swap two characters in the given character array. * @param chars input character array * @param i first index to swap. * @param j second index to swap. */ private static void swap(char[] chars, int i, int j) { if (i == j) return; char temp = chars[i]; chars[i] = chars[j]; chars[j] = temp; } // swap //------ END Solution 1 --------------------------------------------------------------- //------------------------------------------------------------------------------------- //------ Solution 2: For Input with Duplicate Characters ------------------------------ /** * Computes permutation of an string with Duplicate characters. * Obviously, it will also work for the string with unique characters. * @param s input string. * @return Permutations of given input. */ public static List<String> permuteWithDuplicates(String s) { char[] chars = s.toCharArray(); Map<Character, Integer> frequencyMap = createFrequencyMap(chars); List<String> results = new ArrayList<>(); permuteWithDuplicatesHelper(frequencyMap, new char[s.length()], 0, results); return results; } // permuteWithDuplicates //------------------------------------------------------------------------------------- /** * Recursive helper method to compute permutations of a string with duplicate characters. * @param frequencyMap Map holding character counts of input. * @param permutation current permutation * @param cursor current location in permutation * @param results List of all permutations of input. */ private static void permuteWithDuplicatesHelper(Map<Character, Integer> frequencyMap, char[] permutation, int cursor, List<String> results) { if (cursor == permutation.length) { results.add(new String(permutation)); return; } for (Map.Entry<Character, Integer> entry : frequencyMap.entrySet()) { if (entry.getValue() > 0) { permutation[cursor] = entry.getKey(); entry.setValue(entry.getValue() - 1); permuteWithDuplicatesHelper(frequencyMap, permutation, cursor + 1, results); entry.setValue(entry.getValue() + 1); } } } // permuteWithDuplicatesHelper //------------------------------------------------------------------------------------- /** * Utility method to create character counts as a Map. * @param chars input character array * @return Character Counts Map. */ private static Map<Character, Integer> createFrequencyMap(char[] chars) { Map<Character, Integer> result = new HashMap<>(); for (Character c : chars) { if (result.containsKey(c)) { result.put(c, result.get(c) + 1); } else { result.put(c, 1); } } return result; } // createFrequencyMap //------ END Solution 2 --------------------------------------------------------------- } // Permutations