📌  相关文章
📜  最大子序列总和,以使任意两个相邻元素的索引至少相差3

📅  最后修改于: 2021-05-04 21:24:10             🧑  作者: Mango

给定整数数组arr [] ,任务是找到数组中任何子序列的最大和,以使所选序列中的任何两个相邻元素在给定数组中的索引至少相差3。
换句话说,如果选择arr [i],则可以选择的下一个元素是arr [i + 3]arr [i + 4] ,依此类推……但是不能选择arr [i + 1]arr [ i + 2]

例子:

幼稚的方法:我们生成数组的所有可能子集,并检查当前子集是否满足条件;如果是,则将其总和与迄今为止获得的最大和进行比较。这不是一种有效的方法,因为它花费了指数时间。

高效方法:可以使用动态编程解决此问题。让我们决定dp的状态。令dp [i]为从索引0开始到索引i结束的子序列的最大可能和。现在,我们必须找到此状态与低阶状态之间的递归关系。
在这种情况下,对于索引i ,我们有两种选择:

  1. 选择当前索引:在这种情况下,关系将为dp [i] = arr [i] + dp [i – 3]
  2. 跳过当前索引:关系将为dp [i] = dp [i – 1]

我们将选择使我们的结果最大化的路径。因此,最终关系将是:
dp [i] = max(dp [i – 3] + arr [i],dp [i – 1])

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
  
// Function to return the maximum sum
// of the sub-sequence such that two
// consecutive elements have a difference of
// at least 3 in their indices
// in the given array
int max_sum(int a[], int n)
{
  
    int dp[n];
  
    // If there is a single element in the array
    if (n == 1) {
  
        // Either select it or don't
        dp[0] = max(0, a[0]);
    }
  
    // If there are two elements
    else if (n == 2) {
  
        // Either select the first
        // element or don't
        dp[0] = max(0, a[0]);
  
        // Either select the first or the second element
        // or don't select any element
        dp[1] = max(a[1], dp[0]);
    }
    else if (n >= 3) {
  
        // Either select the first
        // element or don't
        dp[0] = max(0, a[0]);
  
        // Either select the first or the second element
        // or don't select any element
        dp[1] = max(a[1], max(0, a[0]));
  
        // Either select first, second, third or nothing
        dp[2] = max(a[2], max(a[1], max(0, a[0])));
  
        int i = 3;
  
        // For the rest of the elements
        while (i < n) {
  
            // Either select the best sum till
            // previous_index or select the current
            // element + best_sum till index-3
            dp[i] = max(dp[i - 1], a[i] + dp[i - 3]);
            i++;
        }
    }
  
    return dp[n - 1];
}
  
// Driver code
int main()
{
    int arr[] = { 1, 2, -2, 4, 3 };
    int n = sizeof(arr) / sizeof(arr[0]);
  
    cout << max_sum(arr, n);
  
    return 0;
}


Java
// Java implementation of the approach
class GFG 
{
  
// Function to return the maximum sum
// of the sub-sequence such that two
// consecutive elements have a difference of
// at least 3 in their indices
// in the given array
static int max_sum(int a[], int n)
{
  
    int []dp = new int[n];
  
    // If there is a single element in the array
    if (n == 1) 
    {
  
        // Either select it or don't
        dp[0] = Math.max(0, a[0]);
    }
  
    // If there are two elements
    else if (n == 2)
    {
  
        // Either select the first
        // element or don't
        dp[0] = Math.max(0, a[0]);
  
        // Either select the first or the second element
        // or don't select any element
        dp[1] = Math.max(a[1], dp[0]);
    }
    else if (n >= 3) 
    {
  
        // Either select the first
        // element or don't
        dp[0] = Math.max(0, a[0]);
  
        // Either select the first or the second element
        // or don't select any element
        dp[1] = Math.max(a[1], Math.max(0, a[0]));
  
        // Either select first, second, third or nothing
        dp[2] = Math.max(a[2], Math.max(a[1], Math.max(0, a[0])));
  
        int i = 3;
  
        // For the rest of the elements
        while (i < n)
        {
  
            // Either select the best sum till
            // previous_index or select the current
            // element + best_sum till index-3
            dp[i] = Math.max(dp[i - 1], a[i] + dp[i - 3]);
            i++;
        }
    }
  
    return dp[n - 1];
}
  
// Driver code
public static void main(String[] args) 
{
    int arr[] = { 1, 2, -2, 4, 3 };
    int n = arr.length;
  
    System.out.println(max_sum(arr, n));
}
}
  
// This code is contributed by Rajput-Ji


Python3
# Python3 implementation of the approach 
  
# Function to return the maximum sum 
# of the sub-sequence such that two 
# consecutive elements have a difference of 
# at least 3 in their indices 
# in the given array 
def max_sum(a, n) :
  
    dp = [0]*n; 
  
    # If there is a single element in the array 
    if (n == 1) :
  
        # Either select it or don't 
        dp[0] = max(0, a[0]); 
  
    # If there are two elements 
    elif (n == 2) :
  
        # Either select the first 
        # element or don't 
        dp[0] = max(0, a[0]); 
  
        # Either select the first or the second element 
        # or don't select any element 
        dp[1] = max(a[1], dp[0]); 
          
    elif (n >= 3) :
  
        # Either select the first 
        # element or don't 
        dp[0] = max(0, a[0]); 
  
        # Either select the first or the second element 
        # or don't select any element 
        dp[1] = max(a[1], max(0, a[0])); 
  
        # Either select first, second, third or nothing 
        dp[2] = max(a[2], max(a[1], max(0, a[0]))); 
  
        i = 3; 
  
        # For the rest of the elements 
        while (i < n) :
  
            # Either select the best sum till 
            # previous_index or select the current 
            # element + best_sum till index-3 
            dp[i] = max(dp[i - 1], a[i] + dp[i - 3]); 
            i += 1; 
  
    return dp[n - 1]; 
  
  
# Driver code 
if __name__ == "__main__" : 
  
    arr = [ 1, 2, -2, 4, 3 ]; 
    n = len(arr); 
  
    print(max_sum(arr, n)); 
  
# This code is contributed by AnkitRai01


C#
// C# implementation of the approach
using System;
  
class GFG
{
      
// Function to return the maximum sum
// of the sub-sequence such that two
// consecutive elements have a difference of
// at least 3 in their indices
// in the given array
static int max_sum(int []a, int n)
{
  
    int []dp = new int[n];
  
    // If there is a single element in the array
    if (n == 1) 
    {
  
        // Either select it or don't
        dp[0] = Math.Max(0, a[0]);
    }
  
    // If there are two elements
    else if (n == 2)
    {
  
        // Either select the first
        // element or don't
        dp[0] = Math.Max(0, a[0]);
  
        // Either select the first or the second element
        // or don't select any element
        dp[1] = Math.Max(a[1], dp[0]);
    }
    else if (n >= 3) 
    {
  
        // Either select the first
        // element or don't
        dp[0] = Math.Max(0, a[0]);
  
        // Either select the first or the second element
        // or don't select any element
        dp[1] = Math.Max(a[1], Math.Max(0, a[0]));
  
        // Either select first, second, third or nothing
        dp[2] = Math.Max(a[2], Math.Max(a[1], Math.Max(0, a[0])));
  
        int i = 3;
  
        // For the rest of the elements
        while (i < n)
        {
  
            // Either select the best sum till
            // previous_index or select the current
            // element + best_sum till index-3
            dp[i] = Math.Max(dp[i - 1], a[i] + dp[i - 3]);
            i++;
        }
    }
  
    return dp[n - 1];
}
  
// Driver code
static public void Main ()
{
          
    int []arr = { 1, 2, -2, 4, 3 };
    int n = arr.Length;
  
    Console.Write(max_sum(arr, n));
}
}
  
// This code is contributed by ajit..


输出:
5

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