给定一个整数数组arr[] ,任务是找到数组中任何子序列的最大和,使得所选序列中的任何两个相邻元素在给定数组中的索引至少相差 3。
换句话说,如果您选择arr[i] ,那么您可以选择的下一个元素是arr[i + 3] 、 arr[i + 4] ,依此类推……但您不能选择arr[i + 1]和arr[我 + 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..
Javascript
5
时间复杂度: O(N)
辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。