给定一个由N 个整数组成的数组arr[]和一个整数K 。任务是通过翻转最多K 个数组元素的符号来找到最大子数组和。
例子:
Input: arr[] = {-6, 2, -1, -1000, 2}, k = 2
Output: 1009
We can flip the signs of -6 and -1000, to get maximum subarray sum as 1009
Input: arr[] = {-1, -2, -100, -10}, k = 1
Output: 100
We can only flip the sign of -100 to get 100
Input: {1, 2, 100, 10}, k = 1
Output: 113
We do not need to flip any elements
方法:该问题可以使用动态规划解决。令 dp[i][j] 是来自索引 i 和 j 次翻转的最大子数组和。可以编写一个递归函数来解决这个问题,我们可以记住它以避免多次函数调用。递归 DP函数(findSubarraySum(ind, flips))将从每个索引调用,初始翻转次数为 0。
ans = max(0, a[ind] + findSubarraySum(ind + 1, flips, n, a, k))
ans = max(ans, -a[ind] + findSubarraySum(ind + 1, flips + 1, n, a, k))
If the value is negative, we are replacing it by 0, similarly as we do in Kadane’s algorithm.
递归函数将有两种状态,一种状态是我们翻转第 i 个索引。如果我们不翻转第 i 个索引,则为第二个。基本情况是如果 ind==n,当我们完成遍历直到最后一个索引时。我们可以使用 memoization 来存储结果,以便稍后使用以避免多次相同的函数调用。所有 dp[i][0] 的最大值将是我们的答案。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
#define right 2
#define left 4
int dp[left][right];
// Function to find the maximum subarray sum with flips
// starting from index i
int findSubarraySum(int ind, int flips, int n, int a[],
int k)
{
// If the number of flips have exceeded
if (flips > k)
return -1e9;
// Complete traversal
if (ind == n)
return 0;
// If the state has previously been visited
if (dp[ind][flips] != -1)
return dp[ind][flips];
// Initially
int ans = 0;
// Use Kadane's algorithm and call two states
ans = max(
0,
a[ind] + findSubarraySum(ind + 1, flips, n, a, k));
ans = max(ans, -a[ind]
+ findSubarraySum(ind + 1, flips + 1,
n, a, k));
// Memoize the answer and return it
return dp[ind][flips] = ans;
}
// Utility function to call flips from index and
// return the answer
int findMaxSubarraySum(int a[], int n, int k)
{
// Create DP array
// int dp[n][k+1];
memset(dp, -1, sizeof(dp));
int ans = -1e9;
// Iterate and call recursive function
// from every index to get the maximum subarray sum
for (int i = 0; i < n; i++)
ans = max(ans, findSubarraySum(i, 0, n, a, k));
// corner case
if (ans == 0 && k == 0)
return *max_element(a, a + n);
return ans;
}
// Driver Code
int main()
{
int a[] = { -1, -2, -100, -10 };
int n = sizeof(a) / sizeof(a[0]);
int k = 1;
cout << findMaxSubarraySum(a, n, k);
return 0;
}
Java
// Java implementation of the approach
import java.util.Arrays;
class GFG {
static int right = 2;
static int left = 4;
static int[][] dp = new int[left][right];
// Function to find the maximum subarray sum with flips
// starting from index i
static int findSubarraySum(int ind, int flips, int n,
int[] a, int k)
{
// If the number of flips have exceeded
if (flips > k)
return (int)(-1e9);
// Complete traversal
if (ind == n)
return 0;
// If the state has previously been visited
if (dp[ind][flips] != -1)
return dp[ind][flips];
// Initially
int ans = 0;
// Use Kadane's algorithm and call two states
ans = Math.max(0, a[ind]
+ findSubarraySum(
ind + 1, flips, n, a, k));
ans = Math.max(ans, -a[ind]
+ findSubarraySum(ind + 1,
flips + 1,
n, a, k));
// Memoize the answer and return it
return dp[ind][flips] = ans;
}
// Utility function to call flips from index and
// return the answer
static int findMaxSubarraySum(int[] a, int n, int k)
{
// Create DP array
// int dp[n,k+1];
for (int i = 0; i < n; i++)
for (int j = 0; j < k + 1; j++)
dp[i][j] = -1;
int ans = (int)(-1e9);
// Iterate and call recursive function
// from every index to get the maximum subarray sum
for (int i = 0; i < n; i++)
ans = Math.max(ans,
findSubarraySum(i, 0, n, a, k));
// corner case
if (ans == 0 && k == 0)
return Arrays.stream(a).max().getAsInt();
return ans;
}
// Driver Code
public static void main(String[] args)
{
int[] a = { -1, -2, -100, -10 };
int n = a.length;
int k = 1;
System.out.println(findMaxSubarraySum(a, n, k));
}
}
// This code is contributed by mits
Python3
# Python3 implementation of the approach
import numpy as np
right = 3;
left = 6;
dp = np.ones((left, right))
dp = -1 * dp
# Function to find the maximum
# subarray sum with flips starting
# from index i
def findSubarraySum(ind, flips, n, a, k) :
# If the number of flips
# have exceeded
if (flips > k) :
return -1e9;
# Complete traversal
if (ind == n) :
return 0;
# If the state has previously
# been visited
if (dp[ind][flips] != -1) :
return dp[ind][flips];
# Initially
ans = 0;
# Use Kadane's algorithm and
# call two states
ans = max(0, a[ind] +
findSubarraySum(ind + 1,
flips, n, a, k));
ans = max(ans, -a[ind] +
findSubarraySum(ind + 1, flips + 1,
n, a, k));
# Memoize the answer and return it
dp[ind][flips] = ans;
return dp[ind][flips] ;
# Utility function to call flips
# from index and return the answer
def findMaxSubarraySum(a, n, k) :
ans = -1e9;
# Iterate and call recursive
# function from every index to
# get the maximum subarray sum
for i in range(n) :
ans = max(ans, findSubarraySum(i, 0, n, a, k));
# corner casae
if ans == 0 and k == 0:
return max(a);
return ans;
# Driver Code
if __name__ == "__main__" :
a = [-1, -2, -100, -10];
n = len(a) ;
k = 1;
print(findMaxSubarraySum(a, n, k));
# This code is contributed by Ryuga
C#
// C# implementation of the approach
using System;
using System.Linq;
class GFG {
static int right = 2;
static int left = 4;
static int[, ] dp = new int[left + 1, right + 1];
// Function to find the maximum subarray sum
// with flips starting from index i
static int findSubarraySum(int ind, int flips, int n,
int[] a, int k)
{
// If the number of flips have exceeded
if (flips > k)
return -(int)1e9;
// Complete traversal
if (ind == n)
return 0;
// If the state has previously been visited
if (dp[ind, flips] != -1)
return dp[ind, flips];
// Initially
int ans = 0;
// Use Kadane's algorithm and call two states
ans = Math.Max(0, a[ind]
+ findSubarraySum(
ind + 1, flips, n, a, k));
ans = Math.Max(ans, -a[ind]
+ findSubarraySum(ind + 1,
flips + 1,
n, a, k));
// Memoize the answer and return it
return dp[ind, flips] = ans;
}
// Utility function to call flips from
// index and return the answer
static int findMaxSubarraySum(int[] a, int n, int k)
{
// Create DP array
// int dp[n][k+1];
for (int i = 0; i < n; i++)
for (int j = 0; j < k + 1; j++)
dp[i, j] = -1;
int ans = -(int)1e9;
// Iterate and call recursive function
// from every index to get the maximum subarray sum
for (int i = 0; i < n; i++)
ans = Math.Max(ans,
findSubarraySum(i, 0, n, a, k));
// corner case
if (ans == 0 && k == 0)
return a.Max();
return ans;
}
// Driver Code
static void Main()
{
int[] a = { -1, -2, -100, -10 };
int n = a.Length;
int k = 1;
Console.WriteLine(findMaxSubarraySum(a, n, k));
}
}
// This code is contributed by mits
Javascript
100
时间复杂度: O(N * K)
辅助空间: O(N * K)