给定一个由N 个正整数组成的数组arr[] ,任务是找到不包含K个连续数组元素的子序列的最大和。
例子:
Input: arr[] = {10, 5, 8, 16, 21}, K = 4
Output: 55
Explanation:
Maximum sum is obtained by picking 10, 8, 16, 21.
Input: arr[] = {4, 12, 22, 18, 34, 12, 25}, K = 5
Output: 111
Explanation:
Maximum sum is obtained by picking 12, 22, 18, 34, 25
朴素的方法:最简单的方法是生成给定数组的所有子集,对于每个子集,检查它是否包含K个连续的数组元素。对于发现不包含K个连续数组元素的子集,计算它们的总和。找出所有这些子序列之和的最大值。
时间复杂度: O(N*2 N )
辅助空间: O(1)
高效的方法:上述解决方案中有许多重叠的子问题,需要反复计算。为了避免重新计算相同的子问题,我们的想法是使用 Memoization 或 Tabulation。请按照以下步骤解决问题:
- 初始化一个数组dp[]以记住每个索引的总和的最大值。
- 现在, dp[i]给出了可以选择的和的最大值,这样从第0个索引到第i个索引没有K 个元素是连续的。
- 基本情况是当i < K 时:
- 由于数组元素都是正数,所以选取第(K)个索引之前的所有元素。
- 所以dp[1] = arr [0]和dp[i] = dp[i -1] + arr[i-1], (1 ≤ i < k )。
- 现在对于i ≥ K :
- 由于无法选取K个连续元素,因此从i到(i – K + 1)至少跳过一个元素,以确保没有K 个元素是连续的。
- 由于任何元素都可以对结果做出贡献,因此跳过从i到(i – K + 1) 的每个元素,并将跟踪最大总和。
- 要跳过第j个元素,将最大总和添加到第(j – 1)个索引,该索引由dp[j – 1]给出,其中从第(j + 1)个索引到第i个索引的所有元素的总和可以是使用前缀数组和以O(1)时间计算。
- 因此更新当前 dp 状态为: dp[i] = max (dp[i], dp[j -1] + prefix[i] – prefix [j]), (i ≤ j ≤ (i – K + 1) ) ,其中前缀数组存储前缀和。
- 在上述步骤之后打印最大和。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the maximum sum
// of a subsequence consisting of
// no K consecutive array elements
int Max_Sum(int arr[], int K, int N)
{
// Stores states of dp
int dp[N + 1];
// Initialise dp state
memset(dp, 0, sizeof(dp));
// Stores the prefix sum
int prefix[N + 1];
prefix[0] = 0;
// Update the prefix sum
for(int i = 1; i <= N; i++)
{
prefix[i] = prefix[i - 1] + arr[i-1];
}
// Base case for i < K
dp[0] = 0;
// For indices less than k
// take all the elements
for(int i = 1; i < K ; i++)
{
dp[i] = prefix[i];
}
// For i >= K case
for(int i = K ; i <= N; ++i)
{
// Skip each element from i to
// (i - K + 1) to ensure that
// no K elements are consecutive
for(int j = i; j >= (i - K + 1); j--)
{
// j-th element is skipped
// Update the current dp state
dp[i] = max(dp[i], dp[j - 1] +
prefix[i] - prefix[j]);
}
}
// dp[N] stores the maximum sum
return dp[N];
}
// Driver Code
int main()
{
// Given array arr[]
int arr[] = { 4, 12, 22, 18, 34, 12, 25 };
int N = sizeof(arr) / sizeof(int);
int K = 5;
// Function Call
cout << Max_Sum(arr, K, N);
return 0;
}
Java
// Java program for the above approach
import java.io.*;
import java.util.*;
class GFG{
// Function to find the maximum sum
// of a subsequence consisting of
// no K consecutive array elements
public static int Max_Sum(int[] arr, int K,
int N)
{
// Stores states of dp
int[] dp = new int[N + 1];
// Initialise dp state
Arrays.fill(dp, 0);
// Stores the prefix sum
int[] prefix = new int[N + 1];
prefix[0] = 0;
// Update the prefix sum
for(int i = 1; i <= N; i++)
{
prefix[i] = prefix[i - 1] + arr[i-1];
}
// Base case for i < K
dp[0] = 0;
// For indices less than k
// take all the elements
for(int i = 1; i <= K - 1; i++)
{
dp[i] = prefix[i];
}
// For i >= K case
for(int i = K ; i <= N; ++i)
{
// Skip each element from i to
// (i - K + 1) to ensure that
// no K elements are consecutive
for(int j = i; j >= (i - K + 1); j--)
{
// j-th element is skipped
// Update the current dp state
dp[i] = Math.max(dp[i], dp[j - 1] +
prefix[i] - prefix[j]);
}
}
// dp[N] stores the maximum sum
return dp[N];
}
// Driver Code
public static void main(String[] args)
{
// Given array arr[]
int[] arr = { 4, 12, 22, 18, 34, 12, 25 };
int N = arr.length;
int K = 5;
// Function Call
System.out.println(Max_Sum(arr, K, N));
}
}
// This code is contributed by akhilsaini
Python3
# Python3 program for the above approach
# Function to find the maximum sum
# of a subsequence consisting of
# no K consecutive array elements
def Max_Sum(arr, K, N):
# Stores states of dp
dp = [0] * (N + 1)
# Stores the prefix sum
prefix = [None] * (N + 1)
prefix[0] = 0
# Update the prefix sum
for i in range(1, N + 1):
prefix[i] = prefix[i - 1] + arr[i - 1]
# Base case for i < K
dp[0] = 0
# For indices less than k
# take all the elements
for i in range(1, K):
dp[i] = prefix[i]
# For i >= K case
for i in range(K, N + 1):
# Skip each element from i to
# (i - K + 1) to ensure that
# no K elements are consecutive
for j in range(i, i - K, -1):
# j-th element is skipped
# Update the current dp state
dp[i] = max(dp[i], dp[j - 1] +
prefix[i] - prefix[j])
# dp[N] stores the maximum sum
return dp[N]
# Driver Code
if __name__ == "__main__":
# Given array arr[]
arr = [ 4, 12, 22, 18, 34, 12, 25 ]
N = len(arr)
K = 5
# Function call
print(Max_Sum(arr, K, N))
# This code is contributed by akhilsaini
C#
// C# program for the above approach
using System;
class GFG{
// Function to find the maximum sum
// of a subsequence consisting of
// no K consecutive array elements
static int Max_Sum(int[] arr, int K, int N)
{
// Stores states of dp
int[] dp = new int[N + 1];
// Initialise dp state
Array.Fill(dp, 0);
// Stores the prefix sum
int[] prefix = new int[N + 1];
prefix[0] = 0;
// Update the prefix sum
for(int i = 1; i <= N; i++)
{
prefix[i] = prefix[i - 1] + arr[i - 1];
}
// Base case for i < K
dp[0] = 0;
// For indices less than k
// take all the elements
for(int i = 1; i <= K - 1; i++)
{
dp[i] = prefix[i];
}
// For i >= K case
for(int i = K; i <= N; ++i)
{
// Skip each element from i to
// (i - K + 1) to ensure that
// no K elements are consecutive
for(int j = i; j >= (i - K + 1); j--)
{
// j-th element is skipped
// Update the current dp state
dp[i] = Math.Max(dp[i], dp[j - 1] +
prefix[i] - prefix[j]);
}
}
// dp[N] stores the maximum sum
return dp[N];
}
// Driver Code
static public void Main()
{
// Given array arr[]
int[] arr = { 4, 12, 22, 18, 34, 12, 25 };
int N = arr.Length;
int K = 5;
// Function Call
Console.WriteLine(Max_Sum(arr, K, N));
}
}
// This code is contributed by akhilsaini
Javascript
输出:
111
时间复杂度: O(N*K),其中 N 是数组中的元素数,K 是输入,因此没有 K 个元素是连续的。
辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。