给定一个由N 个整数组成的数组arr[] ,任务是找到一个非空的最大和 子序列,使得每对连续项具有不同的奇偶校验(偶数或奇数)。
例子:
Input: arr[] = {1, 2, 6, 8, -5, 10}
Output: 14
Explanation: Considering the subsequence {1, 8, -5, 10} which satisfies the given condition, sum of the subsequence = (1 + 8 – 5 + 10) = 14, which is the maximum possible sum.
Input: arr[] = {1, -1, 1, -1}
Output: 1
朴素方法:解决给定问题的最简单方法是生成数组的所有可能子序列,并找到具有不同奇偶校验的所有相邻元素的子序列的最大和。
时间复杂度: O(N*(2 N ))
辅助空间: O(N)
高效方法:上述方法也可以通过使用动态规划进行优化,因为它具有重叠的子问题和最优子结构。子问题可以使用记忆存储在dp[][]表中,其中dp[i][prev]存储从第i 个位置到数组末尾的最大和,当所选的前一个数字的奇偶校验为‘prev’ 时。每个状态有两种情况:
- 如果奇偶校验与前一个元素不同,则包括当前元素。
- 不要包含当前元素。
维护一个布尔变量is_selected以确保至少 从子序列中的数组中选择一个数字,然后在每次递归调用中返回两种情况中的最大值。请按照以下步骤解决问题:
- 通过执行以下步骤定义递归函数maxSum(i, prev, is_selected) :
- 检查基本情况,如果i的值等于N ,则返回0 ,或者如果i的值等于N – 1并且is_selected为false ,则返回arr[i] 。
- 如果已经计算了状态dp[i][prev]的结果,则返回此状态dp[i][prev] 。
- 如果当前元素的奇偶校验与prev不同,则选择当前元素作为子集的一部分,并为索引(i + 1)处的元素递归调用maxSum函数。
- 跳过当前子集的当前元素并递归调用索引(i + 1)的maxSum函数。
- 从当前递归调用中返回两种情况的最大值。
- 完成上述步骤后,打印maxSum(0)的值作为结果。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
int dp[100][3];
// Function to find the maximum sum of
// subsequence with consecutive terms
// having different parity
int maxSum(int* arr, int i, int n,
int prev, bool is_selected)
{
// Base Case
if (i == n) {
return 0;
}
// Store the parity of number at
// the ith position
int cur = abs(arr[i]) % 2;
// If the dp state has already been
// calculated, return it
if (dp[i][prev] != -1) {
return dp[i][prev];
}
// If the array is traversed and
// no element has been selected yet
// then select the current element
if (i == n - 1 && is_selected == 0)
return dp[i][prev] = arr[i];
// If the parity of the current and
// previously selected element are
// different, then select the
// current element
if (cur != prev) {
dp[i][prev] = arr[i]
+ maxSum(arr, i + 1,
n, cur, 1);
}
// Skip the current element and move
// to the next element
dp[i][prev]
= max(dp[i][prev],
maxSum(arr, i + 1, n,
prev, is_selected));
// Return the result
return dp[i][prev];
}
// Function to calculate the maximum sum
// subsequence with consecutive terms
// having different parity
void maxSumUtil(int arr[], int n)
{
// Initialize the dp[] array with -1
memset(dp, -1, sizeof(dp));
// Initially the prev value is set to
// say 2, as the first element can
// anyways be selected
cout << maxSum(arr, 0, n, 2, 0);
}
// Driver Code
int main()
{
int arr[] = { 1, 2, 6, 8, -5, 10 };
int N = sizeof(arr) / sizeof(arr[0]);
maxSumUtil(arr, N);
return 0;
}
14
时间复杂度: O(N)
辅助空间: O(N)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live