给定整数元素的数组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:我们在这里又有两个选择
- 我们更改当前元素的符号,并将其添加到先前的情况2值。
- 我们将当前元素添加到先前的情况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
?>
61
时间复杂度:
空间复杂度: