Combination Sum

Problem

A list of different positive numbers and a target k are given. Print every way to choose numbers that add up to k. A number can be used any number of times. Inside one line the numbers go from small to big, and the lines are in alphabetical (lexicographic) order of their numbers; a way is not repeated in another order. If there is no way, print none.

Constraints

  • 1 <= n <= 10
  • 1 <= k <= 30
  • numbers are different and positive

Examples

Input

4
2 3 6 7
7

Output

2 2 3
7

Solutions

Best approachTime O(number of ways * length)Space O(target)

The loop starts at index start, so the numbers in a way never go down; this removes duplicate ways such as 2 3 2 and 3 2 2. Sorting the numbers also allows an early stop when a number is already too big.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Ways to reach the target.
 * Input   : n, the numbers, then k.
 * Output  : One way per line.
 * Approach: Backtracking.
 * Time    : O(number of ways * length)
 * Space   : O(target)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
        // Step 1: Try the numbers from index "start" on. Going back to a smaller index is not allowed, so no way repeats.
        static void search(int[] numbers, int start, int remaining, java.util.ArrayList<Integer> current, java.util.List<String> found) {
            // Step 2: Base case. When nothing remains, the current choice is a way.
            if (remaining == 0) {
                StringBuilder line = new StringBuilder();
                for (int i = 0; i < current.size(); i++) {
                    line.append(i == 0 ? "" : " ").append(current.get(i));
                }
                found.add(line.toString());
                return;
            }
            for (int i = start; i < numbers.length && numbers[i] <= remaining; i++) {
                // Step 3: Choose the number, search again from the same index (reuse is allowed), then remove it (backtrack).
                current.add(numbers[i]);
                search(numbers, i, remaining - numbers[i], current, found);
                current.remove(current.size() - 1);
            }
        }

    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(int[] a, int k) {
        // Step 4: Sorting lets us stop early and gives the lines in lexicographic order.
        int[] numbers = a.clone();
        java.util.Arrays.sort(numbers);
        java.util.List<String> found = new java.util.ArrayList<>();
        search(numbers, 0, k, new java.util.ArrayList<>(), found);
        if (found.isEmpty()) {
            return new String[] {"none"};
        }
        return found.toArray(new String[0]);
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int size = scanner.nextInt();
        int[] a = new int[size];
        for (int i = 0; i < size; i++) {
            a[i] = scanner.nextInt();
        }
        int k = scanner.nextInt();
        System.out.println(String.join("\n", solve(a, k)));
    }
}
Hints (1)
  1. Why does the recursive call pass i and not i + 1?