简体   繁体   中英

Getting all combinations from a list using recusion, including combinations that use the same number

I have a list of numbers: [10, 13, 15] . I am trying to find the combinations of numbers in the list that add up to or are less than the target of 28.

Currently I have a recursive method:

    public void combinations(ArrayList<Integer>data,int fromIndex, int endIndex)
{
    int sum = 0;
    int target = 28;
    ArrayList<Integer>results = new ArrayList<Integer>();
    if(fromIndex == endIndex)
    {
        return;
    }

    for(int currentIndex = fromIndex; currentIndex < endIndex; currentIndex++)
    {
        if(sum + data.get(currentIndex) <= target)
        {
            results.add(data.get(currentIndex));
            sum +=data.get(currentIndex);
        }

    }

    System.out.println(results);
    combinations(data, fromIndex + 1, endIndex);
}

Currently this outputs: [10, 13],[13, 15],[15] which are correct and I understand why I am getting these solutions as my recursive method has a +1. However other solutions such as [10],[13],[10,10] ect are not included and I was wondering how I would go about implementing this, would I need to change my increments in my recursive method?

public static void combinations(ArrayList<Integer> arr, ArrayList<ArrayList<Integer>> ans, int startIndex, int endIndex, int sum) {

    if(startIndex > endIndex) {
        for(ArrayList<Integer> x : ans) {
            System.out.println(x);
        }
        return;
    }
     ArrayList<Integer> newTemp;
    ArrayList<ArrayList<Integer>> newAns = new ArrayList<ArrayList<Integer>>();
    for(ArrayList<Integer> x : ans) {
        newAns.add(x);
    }
    for(ArrayList<Integer> x : ans) {
        int s = 0;
        newTemp = new ArrayList<Integer>();
        for(Integer v : x) {
            newTemp.add(v);
            s+=v;
        }
        if(s + arr.get(startIndex) <= sum) {
            newTemp.add(arr.get(startIndex));
            newAns.add(newTemp);
        }
    }

    if(arr.get(startIndex) <= sum ) {
        newTemp = new ArrayList<Integer>();
        newTemp.add(arr.get(startIndex));
        newAns.add(newTemp);
    }

    combinations(arr,newAns, startIndex+1, endIndex, sum);
}

I have to rewrite your code as I was unable to think through your code.

Secondly, I have to make a newArrayList all time to avoid ConcurrentModificationException which I have faced the first time and will overcome later after gaining some knowledge about it.

Now, this method should be called as

public static void main (String[] args) {
    ArrayList<Integer> arr = new ArrayList<Integer>();
    arr.add(10);
    arr.add(15);
    arr.add(13);
    arr.add(-5);
    arr.add(28);
    combinations(arr, new ArrayList<ArrayList<Integer>>(), 0, 4, 28);
}

Explanation: I have generalized your question's answer to fit any sum in int range. I have made ArrayList of ArrayList which will print all the combinations at the base case.

  1. I have first added an ArrayList containing single element ie current element if the current element is the <= sum.
  2. Then with all remaining ArrayList, I have calculated the sum of each and then check whether adding the current element into the previous ArrayList holds the above condition.
  3. At the same time I have made new ArrayList and copied all elements while I was calculating the sum of each ArrayList and then if the second case holds good then I added the current element into temp ArrayList and then added the temp ArrayList to the answer ArrayList of ArrayLists.
  4. Then I called the recursion by incrementing the startIndex by 1. Hope it helps.

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