📌  相关文章
📜  最大子序列总和,使得没有 K 个元素是连续的

📅  最后修改于: 2021-09-22 09:53:26             🧑  作者: Mango

给定一个由N 个正整数组成的数组arr[] ,任务是找到不包含K个连续数组元素的子序列的最大和。

例子:

朴素的方法:最简单的方法是生成给定数组的所有子集,对于每个子集,检查它是否包含K个连续的数组元素。对于发现不包含K个连续数组元素的子集,计算它们的总和。找出所有这些子序列之和的最大值。

时间复杂度: O(N*2 N )
辅助空间: O(1)

高效的方法:上述解决方案中有许多重叠的子问题,需要反复计算。为了避免重新计算相同的子问题,我们的想法是使用 Memoization 或 Tabulation。请按照以下步骤解决问题:

  1. 初始化一个数组dp[]以记住每个索引的总和的最大值。
  2. 现在, dp[i]给出了可以选择的和的最大值,这样从第0索引到i索引没有K 个元素是连续的。
  3. 基本情况是当i < K 时
    • 由于数组元素都是正数,所以选取(K)索引之前的所有元素。
    • 所以dp[1] = arr [0]dp[i] = dp[i -1] + arr[i-1], (1 ≤ i < k )。
  4. 现在对于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) ) ,其中前缀数组存储前缀和。
  5. 在上述步骤之后打印最大和。

下面是上述方法的实现:

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 现场工作专业课程学生竞争性编程现场课程