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

📅  最后修改于: 2021-05-17 06:28:47             🧑  作者: Mango

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

例子:

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

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

高效的方法:上述解决方案中有很多重叠的子问题,这些子问题会被反复计算。为了避免对相同的子问题进行重新计算,其想法是使用“记忆化”或“制表”。请按照以下步骤解决问题:

  1. 初始化数组dp []以存储每个索引之和的最大值。
  2. 现在, dp [i]给出可以选择的总和的最大值,以使从第0索引到i索引没有K个元素连续。
  3. 基本情况是当i
    • 由于数组元素都是正数,因此请选择(K)索引之前的所有元素。
    • 因此dp [1] = arr [0]dp [i] = dp [i -1] + arr [i-1],(1≤i
  4. 现在,对于我≥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数组存储前缀和。
  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


输出:
111










时间复杂度: O(N * K),其中N是数组中元素的数量,K是输入,因此没有K个元素是连续的。
辅助空间: O(N)