Reputation: 1
I am having trouble solving this recursion problem. Recursion is quite difficult to understand and be able to code as I am new to coding. The problem is to write a recursive method to find every possible sub-list of a given list. Your method should accept a list of strings as a parameter and print every sub-list that could be created from elements of that list, one per line. Assume there is no duplicates and the list is not null. Do not use any loops.
The only possible way I can think of doing this is with a for loop or use more parameters but I can't per instructions. This is what I have so far. I checked the list api it says there is a subList method you can use. I was able to print the first 5 possible sublists just by substracting -1 from the list size every recursion and then I get an index error. This is very frustrating so if anyone has any tips or pointers that would greatly be appreciated.
If you can possibly solve it with loops, I'd love to see how you would solve it.
public static void main(String[]args){
ArrayList<String> list = new ArrayList<>(List.of("Janet", "Robert", "Morgan", "Char"));
subsets(list);
}
public static void subsets(List<String> list) {
int n = list.size();
if(list.isEmpty()){
System.out.println(list);
}
if(n > 0){
System.out.println(list.subList(0 , n));
}
subsets(list.subList(0,n -1));
}
Upvotes: 0
Views: 770
Reputation: 13195
(I don't know how I ended up being here, this tab really might have been open for 2 years)
If you can possibly solve it with loops, I'd love to see how you would solve it.
With loops it's trivial, you need a loop-pair for start
and end
indices:
const list = ["Janet", "Robert", "Morgan", "Char"];
for (var start = 0; start < list.length; start++)
for (var end = start + 1; end < list.length + 1; end++) // end is exclusive
console.log(list.slice(start, end).join()); // so, this is like list.subList(start,end)
Then it can be rewritten into a single loop, and make it a while
, managing the indices manually:
const list = ["Janet", "Robert", "Morgan", "Char"];
var start = 0;
var end = 1;
while (start < list.length) {
console.log(list.slice(start, end).join());
end++;
if (end > list.length) {
start++;
end = start + 1;
}
}
Then a single loop is easy to write as "recursion":
function sublists(list, start, end) {
console.log(list.slice(start, end).join());
end++;
if (end > list.length) {
start++;
end = start + 1;
}
if (start < list.length)
sublists(list, start, end);
}
sublists(["Janet", "Robert", "Morgan", "Char"], 0, 1);
So, technically we are recursive now, though we don't really benefit from it.
function subsublists(list) {
console.log(list.join());
if (list.length > 1)
subsublists(list.slice(0, list.length - 1));
}
function sublists(list) {
subsublists(list);
if (list.length > 1)
sublists(list.slice(1));
}
sublists(["Janet", "Robert", "Morgan", "Char"], 0);
Or, in Java:
public static void main (String[] args) {
ArrayList<String> list = new ArrayList<>(List.of("Janet", "Robert", "Morgan", "Char"));
sublists(list);
}
public static void subsublists(List<String> list) {
System.out.println(list);
if(list.size()>1)
subsublists(list.subList(0,list.size()-1));
}
public static void sublists(List<String> list) {
subsublists(list);
if(list.size()>1)
sublists(list.subList(1,list.size()));
}
Live version: https://ideone.com/JU44Jj
Output:
[Janet, Robert, Morgan, Char] [Janet, Robert, Morgan] [Janet, Robert] [Janet] [Robert, Morgan, Char] [Robert, Morgan] [Robert] [Morgan, Char] [Morgan] [Char]
Upvotes: 0
Reputation: 159
If we want to permutate all the value in the list then we can use this code->
public static void main(String[] args) {
List<String> list = Arrays.asList("Janet", "Robert", "Morgan", "Char");
recursiveprint(list, new boolean[list.size()], "");
}
private static void recursiveprint(List<String> list, boolean b[], String s) {
System.out.println(s);
for (int j = 0; j < list.size(); j++) {
if (b[j] == false) {
b[j] = true;
recursiveprint(list, b, s + list.get(j)+" ");
b[j] = false;
}
}
}
Upvotes: 0
Reputation: 103
The best solution I came up with is based on randomness, I'll post in even though it is not what is expected by the Java Programming textbook.
You can calculate how many distinct k-combinations of K elements exists in a list of N elements. For example:
The idea is to have as args of the recursive method:
You should then have the following method signature:
public static void subsets(List<String> list, ArrayList<List<String>> alreadyPrinted, int nbOfElementsInTheSubList);
and the call in your main method will be
subsets(list, new ArrayList<>(), list.size());
Now in the body of the recursive method, process as follow (pseudo-code)
I doubt this is an optimal solution, so I bookmarked your topic since I am sincerely curious about the expected code.
Upvotes: 0