How do I make this combinations/permutations method recursive?

浪子不回头ぞ 提交于 2020-01-21 06:04:25

问题


I have an arraylist of Strings that want to have all possible combinations stored into another collection.

For example:

[air,bus,car]
->
[air]
[bus]
[car]
[air,bus]
[air,car]
[bus,air]
[bus,car]
[car,air]
[car,bus]
[air,bus,car]
[air,car,bus]
...
[car,bus,air]

Repetitions are not important. The code right now I have is:

public ArrayList<String> comb(ArrayList<String> wrds, ArrayList<String> str, int size)
{
    ArrayList<String> s = new ArrayList<String>();
    s.addAll(str);
    if(size != a1.size())
    {
        Iterator e = a1.iterator();
        while(e.hasNext())
        {
            s.add((String)e.next());
        }
        size++;
    }
}

I am trying to get it to recursively call itself so it can store the combinations. Can I get any help as to where or which part I am missing in my code?


回答1:


Seeing as this is homework, I'll try to give you background to the answer.

The key to solving this is to use recursion.

First imagine you have two items in your array. You'd could remove the first item to give you your first combination. Adding the remaining item to the first item gives you the second combination. Removing the second item give you the third combination. Adding the remaining item gives you the forth combination. If you had ["air", "bus"] it'd be something like:

["air"]
["air", "bus"]
["bus"]
["bus", "air"]

A method that returns that might look like:

String[][] combinations(String[] strings)

The important things to note are the an array containing a single string can be passed to this method and it can return an array containing an array with a single string in it.

The problem is complicated a little because you have to keep a tally of the string combinations, so before we get to solving that, it's important that you understand recursion.

Imagine you wanted to write a multiplication method that takes two numbers and multiplies them but you only have addition and subtraction at your disposal. You could write a recursive function that adds one of the numbers to itself until the other number reaches an exit condition, something like:

public int multiply(int value1, int value2) 
{
  if (value1 > 1) 
  {
    int remaining = value1 - 1;
    return value2 + multiply(remaining, value2);
  }
  else 
  {
    return value2;
  }
}

You can do just the same thing with an array, only instead to exiting when the a value hit's 1 you exit when the array contains one item, something like:

public String[][] combinations(String[] strings) 
{
  if (strings.length > 1) 
  {
    ...
  }
  else 
  {
    return new String[][]{strings};
  }
}

For reasons with the Java API it's much easier to use java.util.List rather than arrays so you want something like:

public List<List<String>> combinations(List<String> strings) 
{
  if (strings.size()> 1) 
  {
    ...
  }
  else 
  {
    List<List<String>> result = new ArrayList<List<String>>();
    result.add(strings);
    return result;
  }
}

Now it's the ... that's the important bit. You need to keep an list-of-lists that will be the result and iterate over the strings. For each of the strings you can add that string to the results and then you need create a sub-list that is minus the current string, which you use to call the combinations method again iterating over the result adding the current string each list it contains. In code it looks something like:

public List<List<String>> combinations(List<String> strings) 
{
  if (strings.size() > 1) 
  {
    List<List<String>> result = new ArrayList<List<String>>();

    for (String str : strings) 
    {
      List<String> subStrings = new ArrayList<String>(strings);
      subStrings.remove(str);

      result.add(new ArrayList<String>(Arrays.asList(str)));

      for (List<String> combinations : combinations(subStrings)) 
      {
        combinations.add(str);
        result.add(combinations);
      }
    }

    return result;
  }
  else 
  {
    List<List<String>> result = new ArrayList<List<String>>();
    result.add(new ArrayList<String>(strings));
    return result;
  }
}

In summary, what you're doing is reducing the list of strings down to a single item, then combining it with the preceeding items to produce all the possible combinations as the thread returns up the call stack.




回答2:


public static void combination(Object[] array){
         for(int x = 0; x < (1 << array.length); x++){
             System.out.print("[");
             for(int y = 0; y < array.length; y++){
                 if(checkIsOn(x, y){
                    System.out.print(array[y]);
                 }
             }
             System.out.println("]");
         }
    }

    public static boolean checkIsOn(int mast, int position){
         return (mast & (1 << position) > 0);
    }



回答3:


Use the list as a parameter to the recursive function. You can call the function from within itself with a new list containing everything except the first item.



来源:https://stackoverflow.com/questions/14483781/how-do-i-make-this-combinations-permutations-method-recursive

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!