📌  相关文章
📜  生成K个数字的所有可能组合,总和为N

📅  最后修改于: 2021-04-17 15:21:23             🧑  作者: Mango

给定两个整数NK ,任务是根据以下条件找到加起来等于NK个数字的所有有效组合:

  • 仅使用[1,9]范围内的数字。
  • 每个号码最多只能使用一次。

例子:

方法:最简单的想法是使用回溯来解决问题。请按照以下步骤解决问题:

  • 如果N×9小于K ,则打印“不可能”
  • 初始化两个向量 ,分别用于存储组合中是否已经使用数字,以及子向量Vector,用于存储其总和等于K的子集。
  • 初始化vector >,例如输出,以存储所有可能的组合。
  • 现在,定义一个函数,例如Recurrence(N,K,subVector,vis,output,last),以查找所有组合,其中last表示已使用的最后一个数字:
    • 定义一个基本情况,如果N = 0K = 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)