最大产品子阵列

时间:2014-08-31 10:07:54

标签: algorithm dynamic-programming

我有一组n个正实数

我必须找出这个给定数组的最大乘积子阵列。

如何为问题实施DP解决方案?

详细解释溶液的DP配方。

9 个答案:

答案 0 :(得分:4)

由于已知最大总和的解决方案,您可以

  • 将每个数组项目的log计算到另一个数组
  • 将已知算法应用于新数组
  • exp结果就是答案。

(但你可以简单地调整现有的算法,这已经在@ nevets的回答中提到了。用1替换常数0(这是加性中性元素)。)

答案 1 :(得分:3)

它与Maximum Sum of Subarray问题非常相似,比Maximum Product of Subarray which allows negative number容易得多。核心思想是相同的:currentMax = max(a[i], some_operation(currentMax, a[i]))

对于每个元素,我们有两个选项:将它放在一个连续的子数组中,或者用它开始一个新的子数组。

double currentMax = a[0];

for (int i = 1; i < size; i++)
{
     currentMax = max(a[i], currentMax * a[i]);
     best = max(best, currentMax);
}

答案 2 :(得分:2)

我的代码通过了Leetcode OJ:

class Solution {
public:
    int maxProduct(int A[], int n) {
        if (n==0) return 0;

        int maxi = 1, mini = 1;
        int out = INT_MIN;

        for (int i=0;i<n;i++) {
            int oldmaxi = max(maxi,1);
            if (A[i] > 0) {
                maxi = oldmaxi*A[i];
                mini *= A[i];
            } else {
                maxi = mini*A[i];
                mini = oldmaxi*A[i];
            }
            out = max(out,maxi);
        }

        return out;
    }
};

解释可以在这里找到: http://changhaz.wordpress.com/2014/09/23/leetcode-maximum-product-subarray/

答案 3 :(得分:1)

我的Java解决方案,它涵盖了输入数组也可能包含负数的情况:

public class MaximumProductSubarraySolver
{
    public int maxProduct(int[] a)
    {
        int max_so_far = a[0];
        int max_ending_here = a[0];
        int min_ending_here = a[0];
        for (int i = 1; i < a.length; i++)
        {
            int max1 = max_ending_here * a[i];
            int min1 = min_ending_here * a[i];

            max_ending_here = Math.max(a[i], Math.max(min1, max1));
            min_ending_here = Math.min(a[i], Math.min(min1, max1));

            max_so_far  = Math.max(max_so_far, max_ending_here);
        }
        return max_so_far;
    }
}

Leetcode上接受。

更新:以下(非常简单)优化,可在三个数字a[i]max1min1中查找最小值和最大值,效果极佳跳:

public class MaximumProductSubarraySolver {
    public int maxProduct(int[] a) {
        int max_so_far, max_ending_here, min_ending_here;
        max_so_far = max_ending_here = min_ending_here = a[0];

        for (int i = 1; i < a.length; i++)
        {
            int max1 = max_ending_here * a[i];
            int min1 = min_ending_here * a[i];

            // find min and max among a[i], max1, and min1
            // max_ending_here = max(a[i], max1, min1)
            // min_ending_here = min(a[i], max1, min1)
            if(a[i] >= min1)
            {
                if(min1 >= max1)
                {
                    max_ending_here = a[i];
                    min_ending_here = max1;
                }
                else
                {
                    // a[i] >= min1
                    // max1 > min1
                    min_ending_here = min1;
                    max_ending_here = a[i] >= max1 ? a[i] : max1;
                }
            }
            else
            {
                // a[i] < min1
                if(min1 <= max1)
                {
                    max_ending_here = max1;
                    min_ending_here = a[i];
                }
                else
                {
                    //a[i] < min1
                    //max1 < min1
                    max_ending_here = min1;
                    min_ending_here = a[i] <= max1 ? a[i] : max1;
                }
            }

            if(max_ending_here > max_so_far)
            {
                max_so_far  = max_ending_here;
            }
        }

        return max_so_far;
    }
}

Leetcode上的优化代码。

这让我想到我是否可以简化这段代码。这就是我想出的:

public class MaximumProductSubarraySolver {
    public int maxProduct(int[] a) {
        int max_so_far, max_ending_here, min_ending_here;
        max_so_far = max_ending_here = min_ending_here = a[0];

        for (int i = 1; i < a.length; i++)
        {
            if(a[i] < 0)
            {
                // when a[I] < 0
                //     max * a[i] will become min
                //     min * a[i] will become max
                int t = max_ending_here;
                max_ending_here = min_ending_here;
                min_ending_here = t;
            }

            int max1 = max_ending_here * a[i];
            int min1 = min_ending_here * a[i];

            max_ending_here = a[i] > max1 ? a[i] : max1;
            min_ending_here = a[i] < min1 ? a[i] : min1;

            if(max_ending_here > max_so_far)
            {
                max_so_far  = max_ending_here;
            }
        }

        return max_so_far;
    }
}

Leetcode上接受。

答案 4 :(得分:0)

为每个数组,并每次更新max和min。 min * A [i]也许是最大值。 代码在这里,传递给leetcode:

public class Solution {
    public int maxProduct(int[] A) {
        int max = A[0];
        int min = A[0];
        int maxProduct = A[0];

        for(int i = 1; i < A.length; i ++) {
            int temp = max;
            max = Math.max(Math.max(A[i], max*A[i]), min*A[i]);
            min = Math.min(Math.min(A[i], min*A[i]), temp*A[i]);
            if(max > maxProduct)
                maxProduct = max;
        }
        return maxProduct;
    }
}

答案 5 :(得分:0)

以下是Ruby的实现:

def max_subarray_product(arr)
  maxi = 1
  mini = 1
  result = 0

  arr.each do |i|
    temp_max =  maxi > 1 ? maxi : 1
    if (i > 0)
      maxi = temp_max*i
      mini *= i
    else
      maxi = mini*i
      mini = temp_max*i
    end
    result = maxi > result ? maxi : result
  end
  result
end

例如:

a = [6, -3, -10, 0, 2]
puts maxsubarrayproduct(a)

输出:

180

答案 6 :(得分:0)

示例说明:

input = [2,3,-2,4]

product_left_to_right =输入= [2,3,-2,4]

product_right_to_left =输入[::-1] = [4,-2,3,2]

第一次迭代:

6 = 3 * 2 product_left_to_right = [2,6,-2,4]

-8 = -2 * 4 product_right_to_left = [4,-8,3,2]

第二次迭代:

-12 = -2 * 6 product_left_to_right = [2,6,-12,4]

-24 = 3 * -8 product_right_to_left = [4,-8,-24,2]

第三次迭代:

-48 = 4 * -12 product_left_to_right = [2,6,-12,-48]

-48 = 2 * -24 product_right_to_left = [4,-8,-24,-48]

最大值的比较:

product_left_to_right的最大值= [2,6,-12,-48] = 6

product_right_to_left的最大值= [4,-8,-24,-48] = 4

最大(6、4)= 6

返回6

def maxProduct(self, nums: List[int]) -> int:
        l = len(nums)
        nums_l=nums //product_left_to_right 
        nums_r = nums[::-1] //product_right_to_left
        for i in range(1,l,1):
            nums_l[i] *= (nums_l[i-1] or 1) //if meets 0 then restart in-place by itself.
            nums_r[i] *= (nums_r[i-1] or 1) 
        return max(max(nums_l), max(nums_r))

答案 7 :(得分:0)

在Java中非常适合我。所有测试用例都通过了。运行时间1毫秒。

public int maxProduct(int[] nums) {

    int curr_max_prod= nums[0];

    int curr_min_prod= nums[0];

    int prev_max= nums[0];

    int prev_min = nums[0];
    int ans= nums[0];

    for(int i=1;i<nums.length;i++){
        int k= Math.max(nums[i]*prev_max, nums[i]*prev_min);
        curr_max_prod=Math.max(k, nums[i]);

        int h =Math.min(nums[i]*prev_max, nums[i]*prev_min);

        curr_min_prod= Math.min(h, nums[i]);

        ans=Math.max(ans,curr_max_prod);
        prev_max=curr_max_prod;
        prev_min=curr_min_prod;


    }
    return ans;


}

答案 8 :(得分:-1)

由于数字都是正数,所有数字都是正数。