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

📅  最后修改于: 2021-09-22 10:40:32             🧑  作者: Mango

给定一个整数数组arr[] ,任务是找到数组中任何子序列的最大和,使得所选序列中的任何两个相邻元素在给定数组中的索引至少相差 3。
换句话说,如果您选择arr[i] ,那么您可以选择的下一个元素是arr[i + 3]arr[i + 4] ,依此类推……但您不能选择arr[i + 1]arr[我 + 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..


Javascript


输出:
5

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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程