给定一个由N 个非负整数组成的数组A[]和一个整数K ,任务是找到“+”和“-”运算符可以放在数组A[]元素前面的方式数量,例如数组的总和变为K 。
例子:
Input: A[] = {1, 1, 2, 3}, N = 4, K = 1
Output: 3
Explanation: Three possible ways are:
- + 1 + 1 + 2 – 3 = 1
- + 1 – 1 – 2 + 3 = 1
- – 1 + 1 – 1 + 3 = 1
Input: A[] = {1, 1, 1, 1, 1}, N = 5, K = 3
Output: 5
方法:该问题可以基于以下观察来解决:
- 将在该元素前面具有‘+’ 和在该元素前面具有‘-‘的元素的总和存储在变量中,例如P1和P2 ,这样数组的总和变为K 。
- 将数组A[] 的总和存储在一个变量中,比如K 。
- 因此,出现以下等式:
- P1 + P2 = 总和
- P1 – P2 = K
- 求解上述方程得到P1 = (sum + K) / 2 。
- 因此,问题已转化为求总和为 P1 的子集数。
- 如果A的元素等于0 ,则‘+’和‘-‘运算符都在有效排列中工作,因此,可以安全地忽略0并单独计算。
因此,可以使用动态规划解决该问题。请按照以下步骤解决问题:
- 计算和存储阵列A []和0的在A []中分别变量和c的和的数目的元素的总和。
- 如果K大于sum或(sum + K)是奇数,则返回0 。
- 将K与sum 相加并除以2,即sum = (sum + K) / 2 ,这是所需的总和。找到等于该总和的子集数。
- 创建一个维度为N*sum的二维dp数组。其中dp[i][j]表示最多为i-1 且总和为j的子集数。
- 需要考虑的基本情况如下:
- dp[0][i] = 0 ,对于0 <= i <= sum ,因为没有考虑数组A[] 中的元素
- dp[i][0] = 1 ,对于0 <= i <= N ,因为总和0总是可能的。
- 从1到N迭代,并对每个当前索引i执行以下操作:
- 从1迭代到sum并对每个当前索引j执行以下转换:
- 如果A[i – 1]小于j且A[i – 1]不等于0 ,则设置dp[i][j] = dp[i – 1][j] + dp[i – 1][ j – A[i – 1]]。
- 否则,复制之前的状态,即dp[i][j] = dp[i – 1][j]。
- 从1迭代到sum并对每个当前索引j执行以下转换:
- 最后,返回dp[N][sum]和2 c (考虑 0)的乘积,即dp[N][sum]*2 c 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to count number of ways
// '+' and '-' operators can be placed
// in front of array elements to make
// the sum of array elements equal to K
int solve(int A[], int N, int K)
{
// Stores sum of the array
int sum = 0;
// Stores count of 0s in A[]
int c = 0;
// Traverse the array
for (int i = 0; i < N; i++) {
// Update sum
sum += A[i];
// Update count of 0s
if (A[i] == 0)
c++;
}
// Conditions where no arrangements
// are possible which adds up to K
if (K > sum || (sum + K) % 2)
return 0;
// Required sum
sum = (sum + K) / 2;
// Dp array
int dp[N + 1][sum + 1];
// Base cases
for (int i = 0; i <= sum; i++)
dp[0][i] = 0;
for (int i = 0; i <= N; i++)
dp[i][0] = 1;
// Fill the dp array
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= sum; j++) {
if (A[i - 1] <= j && A[i - 1])
dp[i][j] = dp[i - 1][j]
+ dp[i - 1][j - A[i - 1]];
else
dp[i][j] = dp[i - 1][j];
}
}
// Return answer
return dp[N][sum] + pow(2, c);
}
// Driver Code
int main()
{
// Input
int A[] = { 1, 1, 2, 3 };
int N = sizeof(A) / sizeof(A[0]);
int K = 3;
// Function call
cout << solve(A, N, K) << endl;
return 0;
}
Java
// Java program for the above approach
import java.util.*;
class GFG{
// Function to count number of ways
// '+' and '-' operators can be placed
// in front of array elements to make
// the sum of array elements equal to K
static int solve(int A[], int N, int K)
{
// Stores sum of the array
int sum = 0;
// Stores count of 0s in A[]
int c = 0;
// Traverse the array
for (int i = 0; i < N; i++) {
// Update sum
sum += A[i];
// Update count of 0s
if (A[i] == 0)
c++;
}
// Conditions where no arrangements
// are possible which adds up to K
if ((K > sum) || (((sum + K) % 2) != 0))
return 0;
// Required sum
sum = (sum + K) / 2;
// Dp array
int dp[][] = new int[N + 1][sum + 1];
// Base cases
for (int i = 0; i <= sum; i++)
dp[0][i] = 0;
for (int i = 0; i <= N; i++)
dp[i][0] = 1;
// Fill the dp array
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= sum; j++) {
if ((A[i - 1] <= j) && (A[i - 1] != 0))
dp[i][j] = dp[i - 1][j]
+ dp[i - 1][j - A[i - 1]];
else
dp[i][j] = dp[i - 1][j];
}
}
// Return answer
return dp[N][sum] + (int)Math.pow(2, c);
}
// Driver Code
public static void main(String[] args)
{
// Input
int A[] = { 1, 1, 2, 3 };
int N = A.length;
int K = 3;
// Function call
System.out.print(solve(A, N, K));
}
}
// This code is contributed by sanjoy_62.
Python3
# Python3 program for the above approach
# Function to count number of ways
# '+' and '-' operators can be placed
# in front of array elements to make
# the sum of array elements equal to K
def solve(A, N, K):
# Stores sum of the array
sum = 0
# Stores count of 0s in A[]
c = 0
# Traverse the array
for i in range(N):
# Update sum
sum += A[i]
# Update count of 0s
if (A[i] == 0):
c += 1
# Conditions where no arrangements
# are possible which adds up to K
if (K > sum or (sum + K) % 2):
return 0
# Required sum
sum = (sum + K) // 2
# Dp array
dp = [[0 for i in range(sum + 1)]
for j in range(N + 1)]
# Base cases
for i in range(sum + 1):
dp[0][i] = 0
for i in range(N + 1):
dp[i][0] = 1
# Fill the dp array
for i in range(1, N + 1, 1):
for j in range(1, sum + 1, 1):
if (A[i - 1] <= j and A[i - 1]):
dp[i][j] = (dp[i - 1][j] +
dp[i - 1][j - A[i - 1]])
else:
dp[i][j] = dp[i - 1][j]
# Return answer
return dp[N][sum] + pow(2, c)
# Driver Code
if __name__ == '__main__':
# Input
A = [ 1, 1, 2, 3 ]
N = len(A)
K = 3
# Function call
print(solve(A, N, K))
# This code is contributed by SURENDRA_GANGWAR
C#
// C# program for the above approach
using System;
public class GFG
{
// Function to count number of ways
// '+' and '-' operators can be placed
// in front of array elements to make
// the sum of array elements equal to K
static int solve(int[] A, int N, int K)
{
// Stores sum of the array
int sum = 0;
// Stores count of 0s in A[]
int c = 0;
// Traverse the array
for (int i = 0; i < N; i++) {
// Update sum
sum += A[i];
// Update count of 0s
if (A[i] == 0)
c++;
}
// Conditions where no arrangements
// are possible which adds up to K
if ((K > sum) || (((sum + K) % 2) != 0))
return 0;
// Required sum
sum = (sum + K) / 2;
// Dp array
int[, ] dp= new int[N + 1, sum + 1];
// Base cases
for (int i = 0; i <= sum; i++)
dp[0, i] = 0;
for (int i = 0; i <= N; i++)
dp[i,0] = 1;
// Fill the dp array
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= sum; j++) {
if ((A[i - 1] <= j) && (A[i - 1] != 0))
dp[i,j] = dp[i - 1,j]
+ dp[i - 1,j - A[i - 1]];
else
dp[i,j] = dp[i - 1,j];
}
}
// Return answer
return dp[N, sum] + (int)Math.Pow(2, c);
}
// Driver code
static public void Main ()
{
// Input
int[] A = { 1, 1, 2, 3 };
int N = A.Length;
int K = 3;
// Function call
Console.Write(solve(A, N, K));
}
}
// This code is contributed by offbeat
Javascript
输出:
3
时间复杂度: O(N * sum)
辅助空间: O(N * sum)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。