给定一个整数数组和一个数字 K。任务是从给定的数组中找到可被 K 整除的最大和。
例子:
Input: arr[] = {3, 6, 5, 1, 8}, k = 3
Output: 18
Explanation: 18 is formed by the elements 3, 6, 1, 8.
Input: arr = { 43, 1, 17, 26, 15 } , k = 16
Output: 32
Explanation: 32 is formed by the elements 17, 15.
朴素的方法:递归检查所有可能的组合以找到解决方案。该解决方案具有指数时间复杂度,因此效率低下。
高效方法:一种动态规划方法,通过维护一个二维数组dp来存储变量 sum 和i的状态(其中sum是当前和,i 是整数数组的第 i 个索引)。通过重复所有元素,计算包括索引i处的元素以及排除它的总和,并检查是否可被 k 整除。如果是,则将它们中的最大值存储在dp[i][sum] 中并返回。
下面的代码是上述方法的实现:
CPP
#include
using namespace std;
int dp[1001][1001];
// Function to return the maximum sum
// divisible by k from elements of v
int find_max(int i, int sum, vector& v,int k)
{
if (i == v.size())
return 0;
if (dp[i][sum] != -1)
return dp[i][sum];
int ans = 0;
// check if sum of elements excluding the
// current one is divisible by k
if ((sum + find_max(i + 1, sum, v, k)) % k == 0)
ans = find_max(i + 1, sum, v, k);
// check if sum of elements including the
// current one is divisible by k
if((sum + v[i] + find_max(i + 1,(sum + v[i]) % k,
v, k)) % k == 0)
// Store the maximum
ans = max(ans, v[i] + find_max(i + 1,
(sum + v[i]) % k,v, k));
return dp[i][sum] = ans;
}
// Driver code
int main()
{
vector arr = { 43, 1, 17, 26, 15 };
int k = 16;
memset(dp, -1, sizeof(dp));
cout << find_max(0, 0, arr, k);
}
Java
class GFG{
static int [][]dp = new int[1001][1001];
// Function to return the maximum sum
// divisible by k from elements of v
static int find_max(int i, int sum, int []v, int k)
{
if (i == v.length)
return 0;
if (dp[i][sum] != -1)
return dp[i][sum];
int ans = 0;
// check if sum of elements excluding the
// current one is divisible by k
if ((sum + find_max(i + 1, sum, v, k)) % k == 0)
ans = find_max(i + 1, sum, v, k);
// check if sum of elements including the
// current one is divisible by k
if((sum + v[i] + find_max(i + 1,(sum + v[i]) % k,
v, k)) % k == 0)
// Store the maximum
ans = Math.max(ans, v[i] + find_max(i + 1,
(sum + v[i]) % k, v, k));
return dp[i][sum] = ans;
}
// Driver code
public static void main(String[] args)
{
int []arr = { 43, 1, 17, 26, 15 };
int k = 16;
for (int i = 0; i < 1001; i++)
for (int j = 0; j < 1001; j++)
dp[i][j] = -1;
System.out.print(find_max(0, 0, arr, k));
}
}
// This code is contributed by 29AjayKumar
Python 3
# Python3 implementation
dp = [[-1 for i in range(1001)] for j in range(1001)]
# Function to return the maximum sum
# divisible by k from elements of v
def find_max(i, sum, v, k):
if (i == len(v)):
return 0
if (dp[i][sum] != -1):
return dp[i][sum]
ans = 0
# check if sum of elements excluding the
# current one is divisible by k
if ((sum + find_max(i + 1, sum, v, k)) % k == 0):
ans = find_max(i + 1, sum, v, k)
# check if sum of elements including the
# current one is divisible by k
if((sum + v[i] + find_max(i + 1,(sum + v[i]) % k, v, k)) % k == 0):
# Store the maximum
ans = max(ans, v[i] + find_max(i + 1,(sum + v[i]) % k, v, k))
dp[i][sum] = ans
return dp[i][sum]
# Driver code
if __name__ == '__main__':
arr = [43, 1, 17, 26, 15]
k = 16
print(find_max(0, 0, arr, k))
# This code is contributed by Surendra_Gangwar
C#
using System;
class GFG{
static int [,]dp = new int[1001,1001];
// Function to return the maximum sum
// divisible by k from elements of v
static int find_max(int i, int sum, int []v, int k)
{
if (i == v.Length)
return 0;
if (dp[i,sum] != -1)
return dp[i,sum];
int ans = 0;
// check if sum of elements excluding the
// current one is divisible by k
if ((sum + find_max(i + 1, sum, v, k)) % k == 0)
ans = find_max(i + 1, sum, v, k);
// check if sum of elements including the
// current one is divisible by k
if((sum + v[i] + find_max(i + 1,(sum + v[i]) % k,
v, k)) % k == 0)
// Store the maximum
ans = Math.Max(ans, v[i] + find_max(i + 1,
(sum + v[i]) % k, v, k));
return dp[i, sum] = ans;
}
// Driver code
public static void Main(String[] args)
{
int []arr = { 43, 1, 17, 26, 15 };
int k = 16;
for (int i = 0; i < 1001; i++)
for (int j = 0; j < 1001; j++)
dp[i,j] = -1;
Console.Write(find_max(0, 0, arr, k));
}
}
// This code is contributed by 29AjayKumar
Javascript
C++14
#include
using namespace std;
int main()
{
int k=16;
vectorarr={ 43, 1, 17, 26, 15 } ;
int n=arr.size();
vector> dp(n+2, vector(k, 0));
for (int i = 1; i <= n; i++) {
for (int j = 0; j < k ; j++) {
dp[i][j] = dp[i - 1][j];
}
dp[i][arr[i - 1] % k] = max(dp[i][arr[i - 1] % k], arr[i - 1]);
for (int j = 0; j < k; j++) {
int m = (j + arr[i - 1]) % k;
if (dp[i - 1][j] != 0)
dp[i][m] = max(dp[i][m],arr[i - 1] + dp[i - 1][j]);
}
}
cout <
输出
32
使用自顶向下 dp 的迭代实现:
我们将使用总和的索引和模值作为我们的 dp 状态。 dp[i][j] 将存储数组的最大和,直到第 i 个索引的模数为 j。
C++14
#include
using namespace std;
int main()
{
int k=16;
vectorarr={ 43, 1, 17, 26, 15 } ;
int n=arr.size();
vector> dp(n+2, vector(k, 0));
for (int i = 1; i <= n; i++) {
for (int j = 0; j < k ; j++) {
dp[i][j] = dp[i - 1][j];
}
dp[i][arr[i - 1] % k] = max(dp[i][arr[i - 1] % k], arr[i - 1]);
for (int j = 0; j < k; j++) {
int m = (j + arr[i - 1]) % k;
if (dp[i - 1][j] != 0)
dp[i][m] = max(dp[i][m],arr[i - 1] + dp[i - 1][j]);
}
}
cout <
输出
32
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。