📜  长度不超过K的非重叠子数组的最大和

📅  最后修改于: 2021-04-24 14:27:46             🧑  作者: Mango

给定一个长度为N的整数数组’arr’和一个整数’k’,请选择一些不重叠的子数组,使得每个子数组的长度最多为‘k’,则没有两个子数组是相邻的,且所有子数组的和所选子阵列的元素最大。

例子:

Input : arr[] = {-1, 2, -3, 4, 5}, k = 2
Output : 11
Sub-arrays that maximizes sum will be {{2}, {4, 5}}.
Thus, the answer will be 2+4+5 = 11.

Input :arr[] = {1, 1, 1, 1, 1}, k = 1
Output : 3

天真的方法:一种简单的方法是递归地生成满足上述条件的元素的所有可能子集,并找到具有最大总和的子集。
时间复杂度:O(2 N )

高效方法:更好的方法是使用动态编程

假设我们处于索引“ i”。
令dp [i]定义为满足上述条件的子阵列{i,n-1}的所有可能子集的元素的最大和。

我们将有“ K + 1”个可能的选择,即

  1. 拒绝“ i”并求解“ i + 1”。
  2. 选择子数组{i}并求解’i + 2′
  3. 选择子数组{i,i + 1}并求解’i + 3′



    k + 1)选择子数组{i,i + 1,i + 2,..,i + k-1}并求解’i + k + 1’。

因此,递归关系将是:

dp[i] = max(dp[i+1], arr[i]+dp[i+2], arr[i]+arr[i+1]+dp[i+3],
        ...arr[i]+arr[i+1]+arr[i+2]...+arr[i+k-1] + dp[i+k+1])

下面是上述方法的实现:

C++
// C++ program to implement above approach
#include 
#define maxLen 10
using namespace std;
  
// Variable to store states of dp
int dp[maxLen];
  
// Variable to check if a given state has been solved
bool visit[maxLen];
  
// Function to find the maximum sum subsequence
// such that no two elements are adjacent
int maxSum(int arr[], int i, int n, int k)
{
    // Base case
    if (i >= n)
        return 0;
  
    // To check if a state has been solved
    if (visit[i])
        return dp[i];
    visit[i] = 1;
  
    // Variable to store
    // prefix sum for sub-array
    // {i, j}
    int tot = 0;
    dp[i] = maxSum(arr, i + 1, n, k);
  
    // Required recurrence relation
    for (int j = i; j < i + k and j < n; j++) {
        tot += arr[j];
        dp[i] = max(dp[i], tot +
                     maxSum(arr, j + 2, n, k));
    }
  
    // Returning the value
    return dp[i];
}
  
// Driver code
int main()
{
    // Input array
    int arr[] = { -1, 2, -3, 4, 5 };
  
    int k = 2;
  
    int n = sizeof(arr) / sizeof(int);
  
    cout << maxSum(arr, 0, n, k);
  
    return 0;
}


Java
// Java program to implement above approach
import java.io.*;
  
class GFG
{
      
    static int maxLen = 10;
      
    // Variable to store states of dp
    static int dp[] = new int[maxLen];
      
    // Variable to check 
    // if a given state has been solved
    static boolean []visit = new boolean[maxLen];
      
    // Function to find the maximum sum subsequence
    // such that no two elements are adjacent
    static int maxSum(int arr[], int i, 
                    int n, int k)
    {
        // Base case
        if (i >= n)
            return 0;
      
        // To check if a state has been solved
        if (visit[i])
            return dp[i];
        visit[i] = true;
      
        // Variable to store
        // prefix sum for sub-array
        // {i, j}
        int tot = 0;
        dp[i] = maxSum(arr, i + 1, n, k);
      
        // Required recurrence relation
        for (int j = i; j < (i + k) &&
                            (j < n); j++)
        {
            tot += arr[j];
            dp[i] = Math.max(dp[i], tot +
                    maxSum(arr, j + 2, n, k));
        }
      
        // Returning the value
        return dp[i];
    }
  
    // Driver code
    public static void main (String[] args) 
    {
  
        // Input array
        int arr[] = { -1, 2, -3, 4, 5 };
          
        int k = 2;
          
        int n = arr.length;
          
        System.out.println(maxSum(arr, 0, n, k));
    }
}
  
// This code is contributed by ajit.


Python3
# Python3 program to implement above approach 
maxLen = 10
  
# Variable to store states of dp 
dp = [0]*maxLen; 
  
# Variable to check if a given state has been solved 
visit = [0]*maxLen; 
  
# Function to find the maximum sum subsequence 
# such that no two elements are adjacent 
def maxSum(arr, i, n, k) : 
  
    # Base case 
    if (i >= n) :
        return 0; 
  
    # To check if a state has been solved 
    if (visit[i]) : 
        return dp[i]; 
          
    visit[i] = 1; 
  
    # Variable to store 
    # prefix sum for sub-array 
    # {i, j} 
    tot = 0; 
    dp[i] = maxSum(arr, i + 1, n, k); 
  
    # Required recurrence relation 
    j = i
    while (j < i + k and j < n) :
        tot += arr[j]; 
        dp[i] = max(dp[i], tot +
                    maxSum(arr, j + 2, n, k)); 
                      
        j += 1
      
    # Returning the value 
    return dp[i]; 
  
  
# Driver code 
if __name__ == "__main__" : 
  
    # Input array 
    arr = [ -1, 2, -3, 4, 5 ]; 
  
    k = 2; 
  
    n = len(arr); 
  
    print(maxSum(arr, 0, n, k)); 
      
# This code is contributed by AnkitRai01


C#
// C# program to implement above approach
using System;
  
class GFG
{
static int maxLen = 10;
  
// Variable to store states of dp
static int []dp = new int[maxLen];
  
// Variable to check 
// if a given state has been solved
static bool []visit = new bool[maxLen];
  
// Function to find the maximum sum subsequence
// such that no two elements are adjacent
static int maxSum(int []arr, int i, 
                  int n, int k)
{
    // Base case
    if (i >= n)
        return 0;
  
    // To check if a state has been solved
    if (visit[i])
        return dp[i];
    visit[i] = true;
  
    // Variable to store
    // prefix sum for sub-array
    // {i, j}
    int tot = 0;
    dp[i] = maxSum(arr, i + 1, n, k);
  
    // Required recurrence relation
    for (int j = i; j < (i + k) &&
                        (j < n); j++)
    {
        tot += arr[j];
        dp[i] = Math.Max(dp[i], tot +
                  maxSum(arr, j + 2, n, k));
    }
  
    // Returning the value
    return dp[i];
}
  
// Driver code
static public void Main ()
{
  
    // Input array
    int []arr = { -1, 2, -3, 4, 5 };
      
    int k = 2;
      
    int n = arr.Length;
      
    Console.WriteLine (maxSum(arr, 0, n, k));
}
}
  
// This code is contributed by ajit.


输出:
11

时间复杂度: O(n * k)