给定两个整数N和K ,任务是根据以下条件找到加起来等于N的K个数字的所有有效组合:
- 仅使用[1,9]范围内的数字。
- 每个号码最多只能使用一次。
例子:
Input: N = 7, K = 3
Output: 1 2 4
Explanation: The only possible combination is of the numbers {1, 2, 4}.
Input: N = 9, K = 3
Output:
1 2 6
1 3 5
2 3 4
方法:最简单的想法是使用回溯来解决问题。请按照以下步骤解决问题:
- 如果N×9小于K ,则打印“不可能”
- 初始化两个向量
,分别用于存储组合中是否已经使用数字,以及子向量Vector,用于存储其总和等于K的子集。 - 初始化vector
>,例如输出,以存储所有可能的组合。 - 现在,定义一个函数,例如Recurrence(N,K,subVector,vis,output,last),以查找所有组合,其中last表示已使用的最后一个数字:
- 定义一个基本情况,如果N = 0且K = 0,则将subVector推入输出向量。
- 现在,如果N或K小于0,则返回。
- 使用变量i遍历[last,9]的范围,并将i推入subVector并将i标记为已访问。现在,调用递归函数Recurrence(N-1,Ki,subVector,vis,output,last + 1)。
- 在上述步骤的每次迭代中,将i标记为未访问,然后从向量subVector中弹出i 。
- 现在,调用递归函数Recurrence(N,K,subVector,vis,Output,1)。
- 最后,完成上述步骤后,打印vector
输出的向量。
下面是上述方法的实现:
C++
// C++ implementation of
// the above approach
#include
using namespace std;
// Recursive function to find
// all the required combinations
void Recurrence(int N, int K,
vector& sub_vector,
vector& vis,
vector >& output, int last)
{
// Base case
if (N == 0 && K == 0) {
// Push the current subset
// in the array output[][]
output.push_back(sub_vector);
return;
}
// If N or K is less than 0
if (N <= 0 || K <= 0)
return;
// Traverse the range [1, 9]
for (int i = last; i <= 9; i++) {
// If current number is
// not marked visited
if (!vis[i]) {
// Mark i visited
vis[i] = true;
// Push i into the vector
sub_vector.push_back(i);
// Recursive call
Recurrence(N - 1, K - i,
sub_vector, vis,
output, i + 1);
// Pop the last elemnet
// from sub_vector
sub_vector.pop_back();
// Mark i unvisited
vis[i] = false;
}
}
}
// Function to check if required
// combination can be obtained or not
void combinationSum(int N, int K)
{
// If N * 9 is less than K
if (N * 9 < K) {
cout << "Impossible";
return;
}
// Stores if a number can
// be used or not
vector vis(10, false);
// Stores a subset of numbers
// whose sum is equal to K
vector sub_vector;
// Stores list of all the
// possible combinations
vector > output;
// Recursive function call to
// find all combinations
Recurrence(N, K, sub_vector, vis, output, 1);
// Print the output[][] array
for (int i = 0; i < output.size(); i++) {
for (auto x : output[i])
cout << x << " ";
cout << endl;
}
return;
}
// Driver Code
int main()
{
int N = 3, K = 9;
combinationSum(N, K);
return 0;
}
Java
// Java implementation of
// the above approach
import java.util.*;
class GFG{
// Recursive function to find
// all the required combinations
static void
Recurrence(int N, int K, ArrayList sub_vector,
boolean[] vis, ArrayList> output,
int last)
{
// Base case
if (N == 0 && K == 0)
{
// Push the current subset
// in the array output[][]
output.add(new ArrayList<>(sub_vector));
return;
}
// If N or K is less than 0
if (N <= 0 || K <= 0)
return;
// Traverse the range [1, 9]
for(int i = last; i <= 9; i++)
{
// If current number is
// not marked visited
if (!vis[i])
{
// Mark i visited
vis[i] = true;
// Push i into the vector
sub_vector.add(i);
// Recursive call
Recurrence(N - 1, K - i, sub_vector, vis,
output, i + 1);
// Pop the last elemnet
// from sub_vector
sub_vector.remove(sub_vector.size() - 1);
// Mark i unvisited
vis[i] = false;
}
}
}
// Function to check if required
// combination can be obtained or not
static void combinationSum(int N, int K)
{
// If N * 9 is less than K
if (N * 9 < K)
{
System.out.print("Impossible");
return;
}
// Stores if a number can
// be used or not
boolean[] vis = new boolean[10];
// Stores a subset of numbers
// whose sum is equal to K
ArrayList sub_vector = new ArrayList<>();
// Stores list of all the
// possible combinations
ArrayList> output = new ArrayList<>();
// Recursive function call to
// find all combinations
Recurrence(N, K, sub_vector, vis, output, 1);
// Print the output[][] array
for(int i = 0; i < output.size(); i++)
{
for(Integer x : output.get(i))
System.out.print(x + " ");
System.out.println();
}
return;
}
// Driver code
public static void main(String[] args)
{
int N = 3, K = 9;
combinationSum(N, K);
}
}
// This code is contributed by offbeat
输出:
1 2 6
1 3 5
2 3 4
时间复杂度: (N * 2 9 )
辅助空间: O(N)