给定整数数组arr [] ,任务是找到数组中任何子序列的最大和,以使所选序列中的任何两个相邻元素在给定数组中的索引至少相差3。
换句话说,如果选择arr [i],则可以选择的下一个元素是arr [i + 3] , arr [i + 4] ,依此类推……但是不能选择arr [i + 1]和arr [ i + 2] 。
例子:
Input: arr[] = {1, 2, -2, 4, 3}
Output: 5
{1, 4} and {2, 3} are the only sub-sequences
with maximum sum.
Input: arr[] = {1, 2, 72, 4, 3, 9}
Output: 81
幼稚的方法:我们生成数组的所有可能子集,并检查当前子集是否满足条件;如果是,则将其总和与迄今为止获得的最大和进行比较。这不是一种有效的方法,因为它花费了指数时间。
高效方法:可以使用动态编程解决此问题。让我们决定dp的状态。令dp [i]为从索引0开始到索引i结束的子序列的最大可能和。现在,我们必须找到此状态与低阶状态之间的递归关系。
在这种情况下,对于索引i ,我们有两种选择:
- 选择当前索引:在这种情况下,关系将为dp [i] = arr [i] + dp [i – 3] 。
- 跳过当前索引:关系将为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)