简体   繁体   中英

Print out all possible combinations of an ArrayList<ArrayList<String>> recursively

I'm trying to practice recursion, but for the life of me I can't figure out how to do this. Let's say I have 3 or more array lists inside of an array list, and I'd like to print out all possible combinations using recursion. How can I do that?

This is what I have so far

public static void main(String[] args)
{
    ArrayList<ArrayList<String>> combList = new ArrayList<ArrayList<String>>();
    ArrayList<String> fruitList = new ArrayList<String>();
    ArrayList<String> lNameList = new ArrayList<String>();
    ArrayList<String> locationList = new ArrayList<String>();

    fruitList.add("Apple");
    fruitList.add("Orange");
    fruitList.add("Grape");
    combList.add(fruitList);

    colorList.add("Red");
    colorList.add("Green");
    colorList.add("Blue");
    combList.add(colorList);

    numberList.add("One");
    numberList.add("Two");
    numberList.add("Three");
    combList.add(numberList);

    combinations(combList, 0, 0, "");
}

public static void combinations(ArrayList<ArrayList<String>> combList, int listIndex, int itemIndex, String result)
{
    // Am I at the bottom of the y-axis?
    if(listIndex < combList.size())
    {
        //Am I at the bottom of the x-axis?
        if(itemIndex < combList.size())
        {
            ArrayList<String> curList = combList.get(listIndex);
            StringBuilder sb = new StringBuilder();
            sb.append(result).append(curList.get(itemIndex)).append(" ");
            combinations(combList, listIndex + 1, itemIndex, sb.toString());
            combinations(combList, listIndex, itemIndex + 1, result);
        }
        return;
    }
    System.out.println(result);
    return;
}

I'm trying to get it to printout

Apple Red One
Apple Red Two
Apple Red Three
Apple Green One
Apple Green Two
Apple Green Three
Apple Blue One
Apple Blue Two
Apple Blue Three
Orange Red One
Orange Red Two
Orange Red Three
Orange Green One
. . . 
Grape Blue Three

Main problem is that when you move to next list

combinations(combList, listIndex + 1, itemIndex, sb.toString());

you allow iterating over it but only from position held by current itemIndex . This prevents you from iterating over its first elements. Solution would be using

combinations(combList, listIndex + 1, 0, sb.toString());
//                                    ^--start iterating from first list item

Other problem is that you called curList.get(itemIndex) but earlier you tested

if(itemIndex < combList.size()){ ... }

As you see you are comparing index from inner list with size of outer list. This will work only if both sizes are the same - if each inner list have same amount of elements as amount of inner lists. What you need is

if(itemIndex < combList.get(listIndex).size()){ ... }

Next possible problem is fact that you are not handling empty inner lists. Lets say that you have [[a1,a2],[],[c1,c2]] . Because there are no elements in second inner lists your code will not let you move to next inner list since combinations(combList, listIndex, itemIndex + 1, result); is called in if(itemIndex < combList.get(listIndex).size()) . To handle such case you can add else case like

if(itemIndex < combList.get(listIndex).size())
{
    //...
} else if (combList.get(listIndex).isEmpty()){
    combinations(combList, listIndex + 1, 0, result);
}

So your method can look like: Demo

public static void main(String[] args) {

    List<List<String>> combList = new ArrayList<>();
    combList.add(Arrays.asList("a1", "a2", "a3"));
    combList.add(Arrays.asList("b1", "b2"));
    combList.add(Arrays.asList());
    combList.add(Arrays.asList("c1", "c2", "c3"));

    combinations(combList, 0, 0, "");
}

public static void combinations(List<List<String>> combList, int listIndex, int itemIndex, String result)
{
    // Am I at the bottom of the y-axis?
    if(listIndex < combList.size())
    {
        //Am I at the bottom of the x-axis?
        if(itemIndex < combList.get(listIndex).size())
        {
            List<String> curList = combList.get(listIndex);
            StringBuilder sb = new StringBuilder();
            sb.append(result).append(curList.get(itemIndex)).append(" ");
            combinations(combList, listIndex + 1, 0, sb.toString());
            combinations(combList, listIndex, itemIndex + 1, result);
        }else if (combList.get(listIndex).isEmpty()){
            combinations(combList, listIndex + 1, 0, result);
        }
        return;
    }
    System.out.println(result);
    //return; - redundant as last instruction of method
}

Output:

a1 b1 c1 
a1 b1 c2 
a1 b1 c3 
a1 b2 c1 
a1 b2 c2 
a1 b2 c3 
a2 b1 c1 
a2 b1 c2 
a2 b1 c3 
a2 b2 c1 
a2 b2 c2 
a2 b2 c3 
a3 b1 c1 
a3 b1 c2 
a3 b1 c3 
a3 b2 c1 
a3 b2 c2 
a3 b2 c3 

This could be done using Backtracking -

public class Main {
static void back(List<List<Character>> res,String s,int idi)
{
    if(s.length()==res.size())
    {
      
        System.out.println(s);
        return;
    }
    for(int i=0; i<res.get(idi).size();i++)
    {
        s = s + res.get(idi).get(i);
        back(res,s,idi+1);
        s = s.substring(0,s.length()-1);
        
    }
}
public static void main(String[] args) {
    List<List<Character>> res = new ArrayList<List<Character>>();
    Character a[]= new Character[] { 'A', 'B', 'C', 'D' };
        List<Character> list1 = Arrays.asList(a);
    Character a2[]= new Character[] { 'E', 'F', 'G', 'H' };
        List<Character> list2 = Arrays.asList(a);
    Character a3[]= new Character[] { 'I', 'J', 'K', 'L' };
        List<Character> list3 = Arrays.asList(a);
    res.add(list1);
    res.add(list2);
    res.add(list3);
    back(res,"",0);
}
}

Output- AAA AAB AAC AAD ABA ABB ABC ABD ACA ACB ACC ACD ADA ADB ADC ADD BAA BAB BAC BAD BBA BBB BBC BBD BCA BCB BCC BCD BDA BDB BDC BDD CAA CAB CAC CAD CBA CBB CBC CBD CCA CCB CCC CCD CDA CDB CDC CDD DAA DAB DAC DAD DBA DBB DBC DBD DCA DCB DCC DCD DDA DDB DDC DDD

We need to handle one more case in recursion

  public static void main(String[] args)
 {
     ArrayList<ArrayList<String>> combList = new ArrayList<ArrayList<String>>();
     ArrayList<String> fruitList = new ArrayList<String>();
     ArrayList<String> colorList = new ArrayList<String>();
     ArrayList<String> numberList = new ArrayList<String>();

     fruitList.add("Apple");
     fruitList.add("Orange");
     fruitList.add("Grape");
     combList.add(fruitList);

     colorList.add("Red");
     colorList.add("Green");
     colorList.add("Blue");
     combList.add(colorList);

     numberList.add("One");
     numberList.add("Two");
     numberList.add("Three");
     combList.add(numberList);

     combinations(combList, 0, 0, "");
 }

 public static void combinations(ArrayList<ArrayList<String>> combList, int listIndex, int itemIndex, String result)
 {
     ArrayList<String> curList;
     StringBuilder sb ;

     // Am I at the bottom of the y-axis?
     if(listIndex < combList.size())
     {

         curList = combList.get(listIndex);
         //Am I at the bottom of the x-axis?
         if(itemIndex < curList.size())
         {

             sb = new StringBuilder();
             sb.append(result + curList.get(itemIndex) + " ");
             combinations(combList, listIndex + 1, 0, sb.toString());
             combinations(combList, listIndex, itemIndex + 1, result);
         }
         else
         {
             combinations(combList, listIndex + 1, 0, result);
         }

     }
     System.out.println(result);
     return;
 }

Output:

Apple Red One 
Apple Red Two 
Apple Red Three 
Apple Red 
Apple Green One 
Apple Green Two 
Apple Green Three 
Apple Green 
Apple Blue One 
Apple Blue Two 
Apple Blue Three 
Apple Blue 
Apple One 
Apple Two 
Apple Three 
Apple 
Orange Red One 
Orange Red Two 
Orange Red Three 
Orange Red 
Orange Green One 
Orange Green Two 
Orange Green Three 
Orange Green 
Orange Blue One 
Orange Blue Two 
Orange Blue Three 
Orange Blue 
Orange One 
Orange Two 
Orange Three 
Orange 
Grape Red One 
Grape Red Two 
Grape Red Three 
Grape Red 
Grape Green One 
Grape Green Two 
Grape Green Three 
Grape Green 
Grape Blue One 
Grape Blue Two 
Grape Blue Three 
Grape Blue 
Grape One 
Grape Two 
Grape Three 
Grape 
Red One 
Red Two 
Red Three 
Red 
Green One 
Green Two 
Green Three 
Green 
Blue One 
Blue Two 
Blue Three 
Blue 
One 
Two 
Three 

My code. Order in the solution is reversed, but should be an easy fix if this is important. Also the recursive method returns a list of lists that needs to be turned into a String.

import java.util.ArrayList;
import java.util.Arrays;

public class Combinations {
    public static void main(String[] args) {
        ArrayList<ArrayList<String>> combList = new ArrayList<ArrayList<String>>();
        ArrayList<String> fruitList = new ArrayList<String>();
        ArrayList<String> colorList = new ArrayList<String>();
        ArrayList<String> numberList = new ArrayList<String>();

        fruitList.add("Apple");
        fruitList.add("Orange");
        fruitList.add("Grape");
        combList.add(fruitList);

        colorList.add("Red");
        colorList.add("Green");
        colorList.add("Blue");
        combList.add(colorList);

        numberList.add("One");
        numberList.add("Two");
        numberList.add("Three");
        combList.add(numberList);

        ArrayList<ArrayList<String>> combs = combinations(combList);
        for (ArrayList<String> al: combs) {
            System.out.println(String.join(" ", al));
        }
    }

    public static ArrayList<ArrayList<String>> combinations(ArrayList<ArrayList<String>> combList) {
        if (combList.size() == 0) {
            ArrayList<ArrayList<String>> ret = new ArrayList<ArrayList<String>>();
            ret.add(new ArrayList<String>());
            return ret;
        } else {
            ArrayList<String> levelList = combList.remove(0);
            ArrayList<ArrayList<String>> subAnswer = combinations(combList);
            ArrayList<ArrayList<String>> newList = new ArrayList<ArrayList<String>>();
            for (ArrayList<String> solList : subAnswer) {
                for (String s: levelList) {
                    ArrayList<String> newComb = new ArrayList<String>(solList);
                    newComb.add(s);
                    newList.add(newComb);
                }
            }
            return newList;
        }
    }
}
import java.util.Arrays;
import java.util.List;

public class PrintAllCombinations {

public void printCombination(List<List<String>> a, int n, String b) {
    if (n == a.size()) {
        System.out.println(b);
        return;
    }
    for (int j = 0; j < a.get(n).size(); j++)
        printCombination(a, n + 1, b + a.get(n).get(j));
}

public static void main(String[] args) {
    PrintAllCombinations printAllCombinations = new PrintAllCombinations();
    List<List<String>> a = Arrays.asList(Arrays.asList("10 ", "20 ", "30 "), Arrays.asList("40 ", "50 ", "60 "), Arrays.asList("70 ", "80 ", "90 "));
    printAllCombinations.printCombination(a, 0, "");
 }
}

outPut:

  • 10 40 70
  • 10 40 80
  • 10 40 90
  • 10 50 70
  • 10 50 80
  • 10 50 90
  • 10 60 70
  • 10 60 80
  • 10 60 90
  • 20 40 70
  • 20 40 80
  • 20 40 90
  • 20 50 70
  • 20 50 80
  • 20 50 90
  • 20 60 70
  • 20 60 80
  • 20 60 90
  • 30 40 70
  • 30 40 80
  • 30 40 90
  • 30 50 70
  • 30 50 80
  • 30 50 90
  • 30 60 70
  • 30 60 80
  • 30 60 90

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM