给定一个整数元素数组arr[] ,任务是在更改最多两个元素的符号后找到最大可能的子数组和。
例子:
Input: arr[] = {-5, 3, 2, 7, -8, 3, 7, -9, 10, 12, -6}
Output: 61
We can get 61 from index 0 to 10 by
changing the sign of elements at 4th and 7th indices i.e.
-8 and -9. We could have chosen -5 and -6 but this gives us
smaller sum 48.
Input: arr[] = {-5, -3, -18, 0, -4}
Output: 22
方法:这个问题可以用动态规划解决。假设数组中有 n 个元素。我们从最小长度到最大长度构建我们的解决方案。
在每一步,我们将长度 i 的解决方案更改为 i+1。
对于每个步骤,我们有三种情况:
- (最大子数组和)通过改变最多 0 个元素的符号。
- (最大子数组和)通过改变最多 1 个元素的符号。
- (最大子数组和)通过改变最多 2 个元素的符号。
这些情况彼此使用以前的值。
- 案例1:我们有两种选择,要么获取当前元素,要么将当前值添加到同一案例的先前值中。我们存储较大的值。
- 案例2:我们这里有两个选择
- 我们改变当前元素的符号,然后将其添加到 0 或之前的 case 1 值。我们存储较大的。
- 我们取数组的当前元素并将其添加到前一个案例 2 的值中。如果这个值大于我们在(a)案例中得到的值,那么我们更新否则不更新。
- 案例 3:我们在这里再次有两个选择
- 我们改变当前元素的符号并将其添加到之前的 case 2 值中。
- 我们将当前元素添加到之前的 case 3 值中。从 (a) 和 (b) 获得的较大值被存储用于当前情况。
我们更新这 3 种情况的最大值并将其存储在一个变量中。
对于每一步的每种情况,如果给定数组包含 n 个元素,我们采用二维数组 dp[n+1][3]。
Recurrence Relation:
Case 1: dp[i][0] = max(dp[i – 1][0] + arr[i], arr[i])
Case 2: dp[i][1] = max(max(0, dp[i – 1][0]) – arr[i], dp[i – 1][1] + arr[i])
Case 3: dp[i][2] = max(dp[i – 1][1] – arr[i], dp[i – 1][2] + arr[i])
solution = max(solution, max(dp[i][0], dp[i][1], dp[i][2]))
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
#include
using namespace std;
// Function to return the maximum required sub-array sum
int maxSum(int a[], int n)
{
int ans = 0;
int* arr = new int[n + 1];
// Creating one based indexing
for (int i = 1; i <= n; i++)
arr[i] = a[i - 1];
// 2d array to contain solution for each step
int** dp = new int*[n + 1];
for (int i = 0; i <= n; i++)
dp[i] = new int[3];
for (int i = 1; i <= n; ++i) {
// Case 1: Choosing current or (current + previous)
// whichever is smaller
dp[i][0] = max(arr[i], dp[i - 1][0] + arr[i]);
// Case 2:(a) Altering sign and add to previous case 1 or
// value 0
dp[i][1] = max(0, dp[i - 1][0]) - arr[i];
// Case 2:(b) Adding current element with previous case 2
// and updating the maximum
if (i >= 2)
dp[i][1] = max(dp[i][1], dp[i - 1][1] + arr[i]);
// Case 3:(a) Altering sign and add to previous case 2
if (i >= 2)
dp[i][2] = dp[i - 1][1] - arr[i];
// Case 3:(b) Adding current element with previous case 3
if (i >= 3)
dp[i][2] = max(dp[i][2], dp[i - 1][2] + arr[i]);
// Updating the maximum value of variable ans
ans = max(ans, dp[i][0]);
ans = max(ans, dp[i][1]);
ans = max(ans, dp[i][2]);
}
// Return the final solution
return ans;
}
// Driver code
int main()
{
int arr[] = { -5, 3, 2, 7, -8, 3, 7, -9, 10, 12, -6 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << maxSum(arr, n);
return 0;
}
Java
// Java implementation of the approach
class GFG
{
// Function to return the maximum required sub-array sum
static int maxSum(int []a, int n)
{
int ans = 0;
int [] arr = new int[n + 1];
// Creating one based indexing
for (int i = 1; i <= n; i++)
arr[i] = a[i - 1];
// 2d array to contain solution for each step
int [][] dp = new int [n + 1][3];
for (int i = 1; i <= n; ++i)
{
// Case 1: Choosing current or (current + previous)
// whichever is smaller
dp[i][0] = Math.max(arr[i], dp[i - 1][0] + arr[i]);
// Case 2:(a) Altering sign and add to previous case 1 or
// value 0
dp[i][1] = Math.max(0, dp[i - 1][0]) - arr[i];
// Case 2:(b) Adding current element with previous case 2
// and updating the maximum
if (i >= 2)
dp[i][1] = Math.max(dp[i][1], dp[i - 1][1] + arr[i]);
// Case 3:(a) Altering sign and add to previous case 2
if (i >= 2)
dp[i][2] = dp[i - 1][1] - arr[i];
// Case 3:(b) Adding current element with previous case 3
if (i >= 3)
dp[i][2] = Math.max(dp[i][2], dp[i - 1][2] + arr[i]);
// Updating the maximum value of variable ans
ans = Math.max(ans, dp[i][0]);
ans = Math.max(ans, dp[i][1]);
ans = Math.max(ans, dp[i][2]);
}
// Return the final solution
return ans;
}
// Driver code
public static void main (String[] args)
{
int arr[] = { -5, 3, 2, 7, -8, 3, 7, -9, 10, 12, -6 };
int n = arr.length;
System.out.println(maxSum(arr, n));
}
}
// This code is contributed by ihritik
Python3
# Python3 implementation of the approach
# Function to return the maximum
# required sub-array sum
def maxSum(a, n):
ans = 0
arr = [0] * (n + 1)
# Creating one based indexing
for i in range(1, n + 1):
arr[i] = a[i - 1]
# 2d array to contain solution for each step
dp = [[0 for i in range(3)]
for j in range(n + 1)]
for i in range(0, n + 1):
# Case 1: Choosing current or
# (current + previous) whichever is smaller
dp[i][0] = max(arr[i], dp[i - 1][0] + arr[i])
# Case 2:(a) Altering sign and add to
# previous case 1 or value 0
dp[i][1] = max(0, dp[i - 1][0]) - arr[i]
# Case 2:(b) Adding current element with
# previous case 2 and updating the maximum
if i >= 2:
dp[i][1] = max(dp[i][1],
dp[i - 1][1] + arr[i])
# Case 3:(a) Altering sign and
# add to previous case 2
if i >= 2:
dp[i][2] = dp[i - 1][1] - arr[i]
# Case 3:(b) Adding current element
# with previous case 3
if i >= 3:
dp[i][2] = max(dp[i][2],
dp[i - 1][2] + arr[i])
# Updating the maximum value
# of variable ans
ans = max(ans, dp[i][0])
ans = max(ans, dp[i][1])
ans = max(ans, dp[i][2])
# Return the final solution
return ans
# Driver code
if __name__ == "__main__":
arr = [-5, 3, 2, 7, -8, 3,
7, -9, 10, 12, -6]
n = len(arr)
print(maxSum(arr, n))
# This code is contributed by Rituraj Jain
C#
// C# implementation of the approach
using System;
class GFG
{
// Function to return the maximum required sub-array sum
static int maxSum(int [] a, int n)
{
int ans = 0;
int [] arr = new int[n + 1];
// Creating one based indexing
for (int i = 1; i <= n; i++)
arr[i] = a[i - 1];
// 2d array to contain solution for each step
int [, ] dp = new int [n + 1, 3];
for (int i = 1; i <= n; ++i)
{
// Case 1: Choosing current or (current + previous)
// whichever is smaller
dp[i, 0] = Math.Max(arr[i], dp[i - 1, 0] + arr[i]);
// Case 2:(a) Altering sign and add to previous case 1 or
// value 0
dp[i, 1] = Math.Max(0, dp[i - 1, 0]) - arr[i];
// Case 2:(b) Adding current element with previous case 2
// and updating the maximum
if (i >= 2)
dp[i, 1] = Math.Max(dp[i, 1], dp[i - 1, 1] + arr[i]);
// Case 3:(a) Altering sign and add to previous case 2
if (i >= 2)
dp[i, 2] = dp[i - 1, 1] - arr[i];
// Case 3:(b) Adding current element with previous case 3
if (i >= 3)
dp[i, 2] = Math.Max(dp[i, 2], dp[i - 1, 2] + arr[i]);
// Updating the maximum value of variable ans
ans = Math.Max(ans, dp[i, 0]);
ans = Math.Max(ans, dp[i, 1]);
ans = Math.Max(ans, dp[i, 2]);
}
// Return the final solution
return ans;
}
// Driver code
public static void Main ()
{
int [] arr = { -5, 3, 2, 7, -8, 3, 7, -9, 10, 12, -6 };
int n = arr.Length;
Console.WriteLine(maxSum(arr, n));
}
}
// This code is contributed by ihritik
PHP
= 2)
$dp[$i][1] = max($dp[$i][1],
$dp[$i - 1][1] + $arr[$i]);
// Case 3:(a) Altering sign and
// add to previous case 2
if ($i >= 2)
$dp[$i][2] = $dp[$i - 1][1] - $arr[$i];
// Case 3:(b) Adding current element
// with previous case 3
if ($i >= 3)
$dp[$i][2] = max($dp[$i][2],
$dp[$i - 1][2] + $arr[$i]);
// Updating the maximum value of variable ans
$ans = max($ans, $dp[$i][0]);
$ans = max($ans, $dp[$i][1]);
$ans = max($ans, $dp[$i][2]);
}
// Return the final solution
return $ans;
}
// Driver code
$arr = array( -5, 3, 2, 7, -8, 3,
7, -9, 10, 12, -6 );
$n = count($arr) ;
echo maxSum($arr, $n);
// This code is contributed by Ryuga
?>
Javascript
61
时间复杂度:
空间复杂度:
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。