So I have a list:
a 25 b 18 c 18 d 18 e 14 f 14 g 12 ... and so on
For each number that matches, I have to get every permutation of the identifier. The lists I would need from my example would be as follows:
abcdefg abdcefg acbdefg acdbefg adbcefg adcbefg abcdfeg abdcfeg acbdfeg acdbfeg adbcfeg adcbfeg
Steps I am taking currently to solve the problem:
- Read in the list, place each value in an array ([a][12]) and place that in an ArrayList
- I then find if there are any repeating numbers and make note of it within a HashMap
- I then have a for loop set up to go through the HashMap. If the number didn’t repeat, I just add it to the list. If the number did repeat, I use Heap’s algorithm to get every permutation.
If I were to work through it, I would be adding the numbers to a list like this:
a abcd abdc adbc ... abcdef abcdfe abdcef adbcfe ... abcdefg abcdfeg
My current code doesn’t work as intended (generates only one list) and I’m not even sure how to begin writing a code that would continuously generate new lists, while also appending the old lists. I apologize for being lost, I’m in a data structures course right now and it all feels out of my familiarity zone (we just started discussing linked lists).
Note 1: allLists holds all the current lists (a, abcd, adcb,) and permutationList holds all the permutations of the list.
Note 2: I’m doing this through a boolean list, but used letters as an easy visual representation for what I’m trying to accomplish
Code where I expect the problem to be:
public static Boolean[] combine (int i, int j) { int aLen = allLists.get(j).length; int bLen = permutationList.get(i).length; Boolean[] newList = new Boolean[aLen + bLen]; System.arraycopy(allLists.get(j), 0, newList, 0, aLen); System.arraycopy(permutationList.get(i), 0, newList, aLen, bLen); return newList; } public static void setAllLists() { if(allLists.size() == 0) { allLists.add(permutationList.get(0)); } for(int i = 0; i < permutationList.size(); i++) { for(int j = 0; j < allLists.size(); j++) { Boolean[] newList = combine(i,j); if(i == 0) { allLists.set(j, newList); } else { allLists.add(newList); } } } permutationList.clear(); }
Advertisement
Answer
Assumptions:
I don’t know your input format but I have assumed that I have two lists alphabets
which have list of alphabets and values
which have list of corresponding values. Both are equal in length and values
are in decreasing order.
Here’s my approach to the problem:
- Convert the input to a
Map<Integer, List<String>> valuesToListMap = new TreeMap<>(Collections.reverseOrder());
. Why? Because that map will tell the substrings I would need to find permutations for (in your example it would be{a},{b,c,d},{e,f},{g}
and since the map is of typeTreeMap
and the entries in it will be in reverse natural ordering (descending) order, I can ensure the entries in the map are in strictly decreasing order. Sample entry in my map given your input will be18 -> {b,c,d}
- Next, I will iterate through the values of the
valuesToListMap
. I will find permutations of every list. For our example the output would be{{a},{bcd,bdc,cbd,cdb,dbc,dcb},{ef,fe},{g}
. Lets call that collectionpermutationsList
- Next, I will iterate over the
permutationsList
two entries at a time and start appending each element of first entry with each element of second entry . For example, I will append each element of entry{a}
inpermutationsList
with each element of entry{bcd,bdc,cbd,cdb,dbc,dcb}
. So my output after the merge will be{abcd,abdc,acbd,acdb,adbc,adcb}
- Continue doing step 3 recursively and you should have your output
Some notes:
Using TreeMap
ensures we don’t have an output bcdaefg
because that is not in descending order of values.
My solution is below. I have not done any input validation or sanity checks but that should be easy to do:
public class PermutationWithinSubsection { public static void main(String[] args) { List<String> alphabets = Arrays.asList("a","b","c","d","e","f","g"); List<Integer> values = Arrays.asList(25,18,18,18,14,14,12); // Step 1 start Map<Integer, List<String>> valuesToListMap = new TreeMap<>(Collections.reverseOrder()); // Order the map in reverse order of values for(int i=0; i<alphabets.size(); i++) { if(valuesToListMap.containsKey(values.get(i))) { List<String> temp = valuesToListMap.get(values.get(i)); temp.add(alphabets.get(i)); valuesToListMap.put(values.get(i),temp); } else { List<String> temp = new ArrayList<>(); temp.add(alphabets.get(i)); valuesToListMap.put(values.get(i), temp); } } // Step 1 end // Step 2 start List<List<String>> permutationsList = new ArrayList<>(); for(List<String> ip: valuesToListMap.values()) { List<String> result = new PermutationWithinSubsection().permute(ip); permutationsList.add(result); } // Step 2 end // // Step 3 start int count = 1; List<String> l1 = permutationsList.get(0); List<String> r = new PermutationWithinSubsection().merge(l1, permutationsList, count); // // Step 3 end System.out.println("r = " + r); } /** * Find permutations of input list using backtracking * @param ip * @return */ private List<String> permute(List<String> ip) { List<String> list = new ArrayList<>(); backtrack(list, new ArrayList<>(), ip); return list; } private void backtrack(List<String> list, ArrayList<String> tempList, List<String> nums) { if(tempList.size() == nums.size()){ StringBuilder sb = new StringBuilder(); for(String s: tempList) { sb.append(s); } list.add(sb.toString()); } else{ for(int i = 0; i < nums.size(); i++){ if(tempList.contains(nums.get(i))) continue; // element already exists, skip tempList.add(nums.get(i)); backtrack(list, tempList, nums); tempList.remove(tempList.size() - 1); } } } /** * Keep on merging lists till we have merged all * @param l1 * @param resultLists * @param count * @return */ private List<String> merge(List<String> l1, List<List<String>> resultLists, int count) { if(count == resultLists.size()) { return l1; } List<String> l2 = resultLists.get(count); List<String> f = new ArrayList<>(); for(String s1: l1) { for(String s2: l2) { f.add(s1+s2); } } return merge(f,resultLists,++count); }
}
Output: r = [abcdefg, abcdfeg, abdcefg, abdcfeg, acbdefg, acbdfeg, acdbefg, acdbfeg, adbcefg, adbcfeg, adcbefg, adcbfeg]
Hope my explanation was clear. Let me know if you have any questions.