总和为 N 的 K 个数字的所有可能组合的计数
给定一个数字N ,任务是计算从1到N总和等于N的K个数字的组合,允许重复。
例子:
Input: N = 7, K = 3
Output:15
Explanation:The combinations which lead to the sum N = 7 are: {1, 1, 5}, {1, 5, 1}, {5, 1, 1}, {2, 1, 4}, {1, 2, 4}, {1, 4, 2}, {2, 4, 1}, {4, 1, 2}, {4, 2, 1}, {3, 1, 3}, {1, 3, 3}, {3, 3, 1}, {2, 2, 3}, {2, 3, 2}, {3, 2, 2}
Input: N = 5, K = 5
Output: 1
Explanation: {1, 1, 1, 1, 1} is the only combination.
朴素方法:这个问题可以使用递归来解决,然后记忆结果以提高时间复杂度。要解决此问题,请执行以下步骤:
- 创建一个函数,比如countWaysUtil ,它将接受N 、 K 、 sum和dp这四个参数。这里N是需要K 个元素的总和,K是消耗的元素数, sum是到目前为止累积的总和, dp是存储结果的矩阵。此函数将给出获得K数总和的方法数。
- 现在最初使用参数N 、 K 、 sum=0和dp调用countWaysUtil作为填充所有-1的矩阵。
- 在每个递归调用中:
- 检查基本情况:
- 如果和等于N并且K变为 0,则返回 1。
- 如果总和超过N且K仍大于 0,则返回 0。
- 现在,运行从 1 到N的 for 循环,检查每个结果的结果。
- 将所有结果汇总到一个变量cnt中,并在记忆后返回cnt 。
- 检查基本情况:
- 根据以上观察打印答案。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to count
// all the possible combinations
// of K numbers having sum equals to N
int countWaysUtil(int N, int K, int sum,
vector >& dp)
{
// Base Cases
if (sum == N and K == 0) {
return 1;
}
if (sum >= N and K >= 0) {
return 0;
}
if (K < 0) {
return 0;
}
// If the result is already memoised
if (dp[sum][K] != -1) {
return dp[sum][K];
}
// Recursive Calls
int cnt = 0;
for (int i = 1; i <= N; i++) {
cnt += countWaysUtil(
N, K - 1,
sum + i, dp);
}
// Returning answer
return dp[sum][K] = cnt;
}
void countWays(int N, int K)
{
vector > dp(N + 1,
vector(
K + 1, -1));
cout << countWaysUtil(N, K, 0, dp);
}
// Driver Code
int main()
{
int N = 7, K = 3;
countWays(N, K);
}
Java
// Java implementation for the above approach
class GFG {
// Function to count
// all the possible combinations
// of K numbers having sum equals to N
static int countWaysUtil(int N, int K, int sum,
int[][] dp)
{
// Base Cases
if (sum == N && K == 0) {
return 1;
}
if (sum >= N && K >= 0) {
return 0;
}
if (K < 0) {
return 0;
}
// If the result is already memoised
if (dp[sum][K] != -1) {
return dp[sum][K];
}
// Recursive Calls
int cnt = 0;
for (int i = 1; i <= N; i++) {
cnt += countWaysUtil(N, K - 1, sum + i, dp);
}
// Returning answer
return dp[sum][K] = cnt;
}
static void countWays(int N, int K)
{
int[][] dp = new int[N + 1][K + 1];
for (int i = 0; i < N + 1; i++) {
for (int j = 0; j < K + 1; j++) {
dp[i][j] = -1;
}
}
System.out.print(countWaysUtil(N, K, 0, dp));
}
// Driver Code
public static void main(String[] args)
{
int N = 7, K = 3;
countWays(N, K);
}
}
// This code is contributed by ukasp.
Python3
# Python3 program for the above approach
# Function to count all the possible
# combinations of K numbers having
# sum equals to N
def countWaysUtil(N, K, sum, dp):
# Base Cases
if (sum == N and K == 0):
return 1
if (sum >= N and K >= 0):
return 0
if (K < 0):
return 0
# If the result is already memoised
if (dp[sum][K] != -1):
return dp[sum][K]
# Recursive Calls
cnt = 0
for i in range(1, N+1):
cnt += countWaysUtil(N, K - 1, sum + i, dp)
# Returning answer
dp[sum][K] = cnt
return dp[sum][K]
def countWays(N, K):
dp = [[-1 for _ in range(K + 1)]
for _ in range(N + 1)]
print(countWaysUtil(N, K, 0, dp))
# Driver Code
if __name__ == "__main__":
N = 7
K = 3
countWays(N, K)
# This code is contributed by rakeshsahni
C#
// C# implementation for the above approach
using System;
class GFG
{
// Function to count
// all the possible combinations
// of K numbers having sum equals to N
static int countWaysUtil(int N, int K, int sum,
int [,]dp)
{
// Base Cases
if (sum == N && K == 0) {
return 1;
}
if (sum >= N && K >= 0) {
return 0;
}
if (K < 0) {
return 0;
}
// If the result is already memoised
if (dp[sum, K] != -1) {
return dp[sum, K];
}
// Recursive Calls
int cnt = 0;
for (int i = 1; i <= N; i++) {
cnt += countWaysUtil(
N, K - 1,
sum + i, dp);
}
// Returning answer
return dp[sum, K] = cnt;
}
static void countWays(int N, int K)
{
int [,]dp = new int[N + 1, K + 1];
for(int i = 0; i < N + 1; i++) {
for(int j = 0; j < K + 1; j++) {
dp[i, j] = -1;
}
}
Console.Write(countWaysUtil(N, K, 0, dp));
}
// Driver Code
public static void Main()
{
int N = 7, K = 3;
countWays(N, K);
}
}
// This code is contributed by Samim Hossain Mondal.
Javascript
C++
// C++ program for the above approach
#include
using namespace std;
// Method to find factorial of given number
int factorial(int n)
{
if (n == 0)
return 1;
return n * factorial(n - 1);
}
// Function to count all the possible
// combinations of K numbers having
// sum equals to N
int totalWays(int N, int K)
{
// If N
C
// C Program for the above approach
#include
// method to find factorial of given number
int factorial(int n)
{
if (n == 0)
return 1;
return n*factorial(n - 1);
}
// Function to count
// all the possible combinations
// of K numbers having sum equals to N
int totalWays(int N, int K) {
// If N
Java
// Java Program for the above approach
class Solution{
// method to find factorial of given number
static int factorial(int n)
{
if (n == 0)
return 1;
return n*factorial(n - 1);
}
// Function to count
// all the possible combinations
// of K numbers having sum equals to N
static int totalWays(int N, int K) {
// If N
Python3
# Python Program for the above approach
from math import factorial
class Solution:
# Function to count
# all the possible combinations
# of K numbers having sum equals to N
def totalWays(self, N, K):
# If N
C#
// C# Program for the above approach
using System;
public class Solution {
// method to find factorial of given number
static int factorial(int n) {
if (n == 0)
return 1;
return n * factorial(n - 1);
}
// Function to count
// all the possible combinations
// of K numbers having sum equals to N
static int totalWays(int N, int K) {
// If N
Javascript
15
时间复杂度: O(N*K)
空间复杂度: O(N*K)
有效方法:这个问题也可以使用二项式定理来解决。由于所需的总和是 N 和 K 个元素,所以假设 K 个数字是:
a1 + a2 + a3 + a4 + …….. + aK = N
According to the standard principle of partitioning in the binomial theorem, the above equation has a solution which is N+K-1CK-1, where K>=0.
But in our case, K>=1.
So, therefore N should be substituted with N-K and the equation becomes N-1CK-1
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Method to find factorial of given number
int factorial(int n)
{
if (n == 0)
return 1;
return n * factorial(n - 1);
}
// Function to count all the possible
// combinations of K numbers having
// sum equals to N
int totalWays(int N, int K)
{
// If N
C
// C Program for the above approach
#include
// method to find factorial of given number
int factorial(int n)
{
if (n == 0)
return 1;
return n*factorial(n - 1);
}
// Function to count
// all the possible combinations
// of K numbers having sum equals to N
int totalWays(int N, int K) {
// If N
Java
// Java Program for the above approach
class Solution{
// method to find factorial of given number
static int factorial(int n)
{
if (n == 0)
return 1;
return n*factorial(n - 1);
}
// Function to count
// all the possible combinations
// of K numbers having sum equals to N
static int totalWays(int N, int K) {
// If N
Python3
# Python Program for the above approach
from math import factorial
class Solution:
# Function to count
# all the possible combinations
# of K numbers having sum equals to N
def totalWays(self, N, K):
# If N
C#
// C# Program for the above approach
using System;
public class Solution {
// method to find factorial of given number
static int factorial(int n) {
if (n == 0)
return 1;
return n * factorial(n - 1);
}
// Function to count
// all the possible combinations
// of K numbers having sum equals to N
static int totalWays(int N, int K) {
// If N
Javascript
15
时间复杂度: O(N)
辅助空间: O(1)