给定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)
高效的方法:上述解决方案中有很多重叠的子问题,这些子问题会被反复计算。为了避免对相同的子问题进行重新计算,其想法是使用“记忆化”或“制表”。请按照以下步骤解决问题:
- 初始化数组dp []以存储每个索引之和的最大值。
- 现在, dp [i]给出可以选择的总和的最大值,以使从第0个索引到第i个索引没有K个元素连续。
- 基本情况是当i
: - 由于数组元素都是正数,因此请选择第(K)个索引之前的所有元素。
- 因此dp [1] = arr [0]且dp [i] = dp [i -1] + arr [i-1],(1≤i
- 现在,对于我≥K :
- 由于无法选取K个连续元素,因此请从i到(i – K + 1)(包括1和2)之间至少跳过一个元素,以确保没有K个元素是连续的。
- 由于任何元素都可以影响结果,因此请将每个元素从i跳过到(i – K + 1)(含),并将跟踪最大和。
- 要跳过第j个元素,请添加最大总和,直到dp [j – 1]给出的第(j – 1)个索引加上第(j + 1)个索引到第i个索引的所有元素的和。使用前缀数组总和在O(1)时间中计算得出。
- 因此,将当前dp状态更新为: dp [i] = max(dp [i],dp [j -1] +前缀[i] –前缀[j]),(i≤j≤(i – K + 1) ) ,其中prefix数组存储前缀和。
- 完成上述步骤后,打印最大金额。
下面是上述方法的实现:
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
输出:
111
时间复杂度: O(N * K),其中N是数组中元素的数量,K是输入,因此没有K个元素是连续的。
辅助空间: O(N)