反转增益最大子数组和题解

133 阅读2分钟

原题链接:翻转增益的最大子数组和 - MarsCode

题目描述:

小C面对一个由整数构成的数组,他考虑通过一次操作提升数组的潜力。这个操作允许他选择数组中的任一子数组并将其翻转,目的是在翻转后的数组中找到具有最大和的子数组。小C对这个可能性很感兴趣,并希望知道翻转后的数组中可能得到的最大子数组和是多少。

例如,数组是 1, 2, 3, -1, 4。小C可以选择翻转子数组 -1, 4 得到 1, 2, 3, 4, -1 或者翻转 1, 2, 3, -1 得到 -1, 3, 2, 1, 4,在这两种情况下,最大的子数组和都是 10。

备注:子数组 是数组中的一个连续部分。

输入

  • N: 数组的长度
  • data_array: 一个长度为 N 的整数数组

输出

请你返回执行翻转操作后(也可以选择不翻转),数组中可能获得的最大子数组和。


测试样例

样例1:

输入:N = 5,data_array = [1, 2, 3, -1, 4]
输出:10

样例2:

输入:N = 4,data_array = [-3, -1, -2, 3]
输出:3

样例3:

输入:N = 3,data_array = [-1, -2, -3]
输出:-1

样例4:

输入:N = 6,data_array = [-5, -9, 6, 7, -6, 2]
输出:15

样例5:

输入:N = 7,data_array = [-8, -1, -2, -3, 4, -5, 6]
输出:10

思路解析:

步骤一:

计算出不做任何反转前的最大子数组和,用Kadaen法:

private static int Kadane(int[] data_array) {
        int current_max = data_array[0];
        int global_max = data_array[0];
        for (int i = 1; i < data_array.length; i++) {
            int num = data_array[i];
            current_max = Math.max(num, current_max + num);
            global_max = Math.max(global_max, current_max);
        }    
             return global_max;
    }

步骤二:

实现将某个子数组反转的过程:

private static int[] flipSubarray(int[] array, int start, int end) {
        while (start < end) {
            int tmp = array[start];
            array[start] = array[end];
            array[end] = tmp;
            end--;
            start++;
        }
         return array;
    }

最后:

循环找到最大值:

public static int solution(int N, int[] data_array) {

        int maxSumWithFlip = Kadane(data_array);
        for (int i = 0; i < N; i++) {
            for (int j = i + 1; j < N; j++) {
                int[] tmp_array = data_array.clone();
                int[] flippedArray = flipSubarray(tmp_array, i, j);
                maxSumWithFlip = Math.max(maxSumWithFlip, Kadane(flippedArray));
            }
        }
            return maxSumWithFlip;
    }


全部代码:

public static int solution(int N, int[] data_array) {

        int maxSumWithFlip = Kadane(data_array);
        for (int i = 0; i < N; i++) {
            for (int j = i + 1; j < N; j++) {
                int[] tmp_array = data_array.clone();
                int[] flippedArray = flipSubarray(tmp_array, i, j);
                maxSumWithFlip = Math.max(maxSumWithFlip, Kadane(flippedArray));
            }
        }
            return maxSumWithFlip;
    }


    private static int Kadane(int[] data_array) {
        int current_max = data_array[0];
        int global_max = data_array[0];
        for (int i = 1; i < data_array.length; i++) {
            int num = data_array[i];
            current_max = Math.max(num, current_max + num);
            global_max = Math.max(global_max, current_max);
        }    
             return global_max;
    }


    private static int[] flipSubarray(int[] array, int start, int end) {
        while (start < end) {
            int tmp = array[start];
            array[start] = array[end];
            array[end] = tmp;
            end--;
            start++;
        }
         return array;
    }