在数组中打印最大连续乘积的子数组

时间:2020-05-31 12:46:00

标签: java arrays data-structures

最大乘积子数组 给定一个同时包含正整数和负整数的数组,请找到最大积的子数组。 例子:

输入:arr [] = {6,-3,-10,0,2} 输出:子数组为{6,-3,-10}

输入:arr [] = {-1,-3,-10,0,60} 输出:子数组为{60}

输入:arr [] = {-2,-3,0,-2,-40} 输出:子数组为{-2,-40}

注意:查找最大乘积是使用kadane算法完成的,在该示例中,我尝试重用它来查找子数组,但无法破坏查找起始索引的部分,因此查找终止索引很容易。最终索引是res

public int maxProductSubArray(int arr[], int len) {

        int res = arr[0];

        int max = arr[0];
        int min = arr[0];

        for (int i = 1; i < len; i++) {

            int temp = max;

            max = Math.max(Math.max(max * arr[i], min * arr[i]), arr[i]);
            min = Math.min(Math.min(temp * arr[i], min * arr[i]), arr[i]);

            res = Math.max(res, max);
        }

        return res;

    }

但无法解决查找子阵列的问题。

2 个答案:

答案 0 :(得分:2)

有几种方法可以解决此问题:

  • 蛮力
  • 分而治之
  • 回溯

我只会向您展示蛮力解决方案。这不是最快的解决方案,但我认为这是最清晰易懂的解决方案:

public class SubArray {

    public static int findMax(int[] num) {

        int max = num[0];
        int start = 0;
        int end = 0;
        for(int i = 0; i < num.length; i++) {   //Iterating over every possible starting position
            for(int j = i; j < num.length; j++) { //Iterating over every possible end position
                int multiply = 1;
                for(int k = i; k <= j; k++) {   //Multiply from start to end
                    multiply *= num[k];
                }
                if(max < multiply) {    //Did we find a new maximum?
                    max = multiply;
                    start = i;
                    end = j;
                }
            }
        }

        System.out.print("The subarray is {");  //Print subarray with highest product
        for(int i = start; i <= end; i++) {
            System.out.print(num[i]);
            if(i < end) {
                System.out.print(", ");
            }
        }
        System.out.println("}");

        return max;
    }

    public static void main(String[] args) {
        int[] array = {6, -3, -10, 0, 2} ;
        int max = findMax(array);
        System.out.println("Maximal product is: " + max);
    }   
}

答案 1 :(得分:0)

通过分而治之可以有效地解决这个问题。

假设您要解决子数组[l, r]的问题;然后,假设c = (l + r) / 2[l, c][c + 1, r]中的子数组,或是包含cc + 1的某个子数组中的子数组。

然后,我们定义一个函数f(l, r)来返回子段的答案;然后,要计算此函数,请首先递归调用f(l, c)f(c + 1, r)并选择最大值作为临时答案。然后计算段[c, c]的乘法,然后计算[c - 1, c]等(使用multiplication of [c - k, c] = multiplication of [c - k + 1, c] * array[c - k]),并计算所有此类段的最大和最小乘法。对c[c + 1, c + 1][c + 1, c + 2]等右边的段执行相同的操作,然后,答案将是临时答案,即最大值的乘积或最小值的乘法或最小值和最大值的乘积,反之亦然(如果乘积为负,则需要最小乘以最大值)。返回这四个值中的最大值或临时答案作为函数结果。

如果有必要,除了返回乘法函数的值外,还可以返回达到这些值的段。

此解决方案使用Θ(n log n)时间和Θ(n)空间。