给定正整数数组arr []和x的总和,请在arr []中找到总和等于x的所有唯一组合。可以从arr []无限次数中选择相同的重复数。组合中的元素(a1,a2,…,ak)必须以降序打印。 (即a1 <= a2 <=…<= ak)。
组合本身必须按升序排序,即,应首先打印具有最小第一元素的组合。如果没有可能的组合,则打印“空”(不带引号)。
例子:
Input : arr[] = 2, 4, 6, 8
x = 8
Output : [2, 2, 2, 2]
[2, 2, 4]
[2, 6]
[4, 4]
[8]
由于问题在于获得所有可能的结果,而不是最佳结果或结果数量,因此我们不需要考虑DP(动态编程),因此需要递归来处理它。
我们应该使用以下算法。
1. Sort the array(non-decreasing).
2. First remove all the duplicates from array.
3. Then use recursion and backtracking to solve
the problem.
(A) If at any time sub-problem sum == 0 then
add that array to the result (vector of
vectors).
(B) Else if sum is negative then ignore that
sub-problem.
(C) Else insert the present array in that
index to the current vector and call
the function with sum = sum-ar[index] and
index = index, then pop that element from
current index (backtrack) and call the
function with sum = sum and index = index+1
以下是上述步骤的C++实现。
C++
// C++ program to find all combinations that
// sum to a given value
#include
using namespace std;
// Print all members of ar[] that have given
void findNumbers(vector& ar, int sum,
vector >& res, vector& r,
int i)
{
// if we get exact answer
if (sum == 0) {
res.push_back(r);
return;
}
// Recur for all remaining elements that
// have value smaller than sum.
while (i < ar.size() && sum - ar[i] >= 0) {
// Till every element in the array starting
// from i which can contribute to the sum
r.push_back(ar[i]); // add them to list
// recur for next numbers
findNumbers(ar, sum - ar[i], res, r, i);
i++;
// Remove number from list (backtracking)
r.pop_back();
}
}
// Returns all combinations
// of ar[] that have given
// sum.
vector > combinationSum(vector& ar,
int sum)
{
// sort input array
sort(ar.begin(), ar.end());
// remove duplicates
ar.erase(unique(ar.begin(), ar.end()), ar.end());
vector r;
vector > res;
findNumbers(ar, sum, res, r, 0);
return res;
}
// Driver code
int main()
{
vector ar;
ar.push_back(2);
ar.push_back(4);
ar.push_back(6);
ar.push_back(8);
int n = ar.size();
int sum = 8; // set value of sum
vector > res = combinationSum(ar, sum);
// If result is empty, then
if (res.size() == 0) {
cout << "Emptyn";
return 0;
}
// Print all combinations stored in res.
for (int i = 0; i < res.size(); i++) {
if (res[i].size() > 0) {
cout << " ( ";
for (int j = 0; j < res[i].size(); j++)
cout << res[i][j] << " ";
cout << ")";
}
}
}
Java
// Java program to find all combinations that
// sum to a given value
import java.io.*;
import java.util.*;
class GFG {
static ArrayList >
combinationSum(ArrayList arr, int sum)
{
ArrayList > ans
= new ArrayList<>();
ArrayList temp = new ArrayList<>();
// first do hashing since hashset does not always
// sort
// removing the duplicates using HashSet and
// Sorting the arrayList
Set set = new HashSet<>(arr);
arr.clear();
arr.addAll(set);
Collections.sort(arr);
findNumbers(ans, arr, sum, 0, temp);
return ans;
}
static void
findNumbers(ArrayList > ans,
ArrayList arr, int sum, int index,
ArrayList temp)
{
if (sum == 0) {
// Adding deep copy of list to ans
ans.add(new ArrayList<>(temp));
return;
}
for (int i = index; i < arr.size(); i++) {
// checking that sum does not become negative
if ((sum - arr.get(i)) >= 0) {
// adding element which can contribute to
// sum
temp.add(arr.get(i));
findNumbers(ans, arr, sum - arr.get(i), i,
temp);
// removing element from list (backtracking)
temp.remove(arr.get(i));
}
}
}
// Driver Code
public static void main(String[] args)
{
ArrayList arr = new ArrayList<>();
arr.add(2);
arr.add(4);
arr.add(6);
arr.add(8);
int sum = 8;
ArrayList > ans
= combinationSum(arr, sum);
// If result is empty, then
if (ans.size() == 0) {
System.out.println("Empty");
return;
}
// print all combinations stored in ans
for (int i = 0; i < ans.size(); i++) {
System.out.print("(");
for (int j = 0; j < ans.get(i).size(); j++) {
System.out.print(ans.get(i).get(j) + " ");
}
System.out.print(") ");
}
}
}
Python3
# Python3 program to find all combinations that
# sum to a given value
def combinationSum(arr, sum):
ans = []
temp = []
# first do hashing nothing but set{}
# since set does not always sort
# removing the duplicates using Set and
# Sorting the List
arr = sorted(list(set(arr)))
findNumbers(ans, arr, temp, sum, 0)
return ans
def findNumbers(ans, arr, temp, sum, index):
if(sum == 0):
# Adding deep copy of list to ans
ans.append(list(temp))
return
# Iterate from index to len(arr) - 1
for i in range(index, len(arr)):
# checking that sum does not become negative
if(sum - arr[i]) >= 0:
# adding element which can contribute to
# sum
temp.append(arr[i])
findNumbers(ans, arr, temp, sum-arr[i], i)
# removing element from list (backtracking)
temp.remove(arr[i])
# Driver Code
arr = [2, 4, 6, 8]
sum = 8
ans = combinationSum(arr, sum)
# If result is empty, then
if len(ans) <= 0:
print("empty")
# print all combinations stored in ans
for i in range(len(ans)):
print("(", end=' ')
for j in range(len(ans[i])):
print(str(ans[i][j])+" ", end=' ')
print(")", end=' ')
# This Code Is Contributed by Rakesh(vijayarigela09)
输出
( 2 2 2 2 ) ( 2 2 4 ) ( 2 6 ) ( 4 4 ) ( 8 )