How to Calculate all Unique Combinations of a Target using Backtracking in Java

2 min read 417 words

Table of Contents

The challenge

Given an array of distinct integers candidates and a target integer target, return a list of all unique combinations of candidates where the chosen numbers sum to target. You may return the combinations in any order.

The same number may be chosen from candidates an unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different.

Example 1:

Input: candidates = [2,3,6,7], target = 7
Output: [[2,2,3],[7]]
Explanation:
2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times.
7 is a candidate, and 7 = 7.
These are the only two combinations.

Example 2:

Input: candidates = [2,3,5], target = 8
Output: [[2,2,2,2],[2,3,3],[3,5]]

Example 3:

Input: candidates = [2], target = 1
Output: []

Example 4:

Input: candidates = [1], target = 1
Output: [[1]]

Example 5:

Input: candidates = [1], target = 2
Output: [[1,1]]

Constraints:

  • 1 <= candidates.length <= 30
  • 1 <= candidates[i] <= 200
  • All elements of candidates are distinct.
  • 1 <= target <= 500

The solution in Java code

This problem is perform for using a backtracking algorithm to solve it.

Backtracking is an algorithmic-technique for solving problems recursively by trying to build a solution incrementally, one piece at a time, removing those solutions that fail to satisfy the constraints of the problem at any point of time (by time, here, is referred to the time elapsed till reaching any level of the search tree).

geeksforgeeks.org

Using this technique, we can write the following code to solve our challenge:

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        // create a return variable
        List<List<Integer>> res = new ArrayList<>();
        
        // use backtracking to attempt to solve
        // we will pass the following:
        back(res, 
             new ArrayList<>(), // - return variable
             target,            // - the target number
             candidates,        // - all candidates
             0                  // - where we should start
        );
        
        // return our answer
        return res;
    }
    
    // our backtracking helper method
    private void back(List<List<Integer>> res, 
                      List<Integer> tmp, 
                      int remains, 
                      int[] nums, 
                      int start) {
        // if our target is less than 0, get out
        if (remains<0) return;
        
        // if the remaining target is 0, return the target
        if (remains==0) {
            res.add(new ArrayList<>(tmp));
            return;
        }
        
        // loop through all candidates
        for (int i=start; i<nums.length; i++) {
            // add each one
            tmp.add(nums[i]);
            // perform another round of backtracking
            back(res, 
                 tmp, 
                 remains-nums[i], 
                 nums, 
                 i
            );
            // remove the last item
            tmp.remove(tmp.size()-1);
        }
    }
}
Tags:
Andrew
Andrew

Andrew is a visionary software engineer and DevOps expert with a proven track record of delivering cutting-edge solutions that drive innovation at Ataiva.com. As a leader on numerous high-profile projects, Andrew brings his exceptional technical expertise and collaborative leadership skills to the table, fostering a culture of agility and excellence within the team. With a passion for architecting scalable systems, automating workflows, and empowering teams, Andrew is a sought-after authority in the field of software development and DevOps.

Tags