📌  相关文章
📜  通过翻转最多 K 个数组元素的符号来实现最大子数组和

📅  最后修改于: 2021-09-22 10:06:17             🧑  作者: Mango

给定一个由N 个整数组成的数组arr[]和一个整数K 。任务是通过翻转最多K 个数组元素的符号来找到最大子数组和。

例子:

方法:该问题可以使用动态规划解决。令 dp[i][j] 是来自索引 i 和 j 次翻转的最大子数组和。可以编写一个递归函数来解决这个问题,我们可以记住它以避免多次函数调用。递归 DP函数(findSubarraySum(ind, flips))将从每个索引调用,初始翻转次数为 0。

递归函数将有两种状态,一种状态是我们翻转第 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)