Maximum Product Subarray--lintcode

Description

Find the contiguous subarray within an array (containing at least one number) which has the largest product.

Example

For example, given the array [2,3,-2,4], the contiguous subarray [2,3] has the largest product = 6.

我的思路:动态规划题。这个题目要注意的是负数。如果全是正数,全部相乘即为最大。如果有负数,这个负数该不该乘。
既然是动态规划,一般两个for循环不能少。然后画图。可是这个图 该怎么画图,有点饶人。
这里写图片描述
图中虚线的下面部分是为nums[i]。上面部分是nums[i]*nums[i-1].画出这样的图之后 从矩阵中找到最大值。这个虽然是二维数组,但是我们可以优化成一维数组。而且冲与其从矩阵中找最大值,不如一边给矩阵赋值,一遍找最大值。

 public int maxProduct(int[] nums) {
        // write your code here
        if(nums==null) return 0;
        int[] temp=new int[nums.length];
        int max=nums[0];
        temp[0]=nums[0];
        for(int i=1;i<nums.length;i++){
            temp[i]=nums[i]*temp[i-1];
            max=temp[i]>max?temp[i]:max;
        }
        //System.out.println(max);
        for(int i=1;i<nums.length;i++){
            for(int j=i;j<nums.length;j++){
                if(i==j) temp[j]=nums[i];
                else{
                      temp[j]=nums[j]*temp[j-1];
                }                
                max=temp[j]>max?temp[j]:max;              
            }
        }
        return max;

    }

别人的思路:在维护一个局部最大的同时,在维护一个局部最小,这样如果下一个元素遇到负数时,就有可能与这个最小相乘得到当前最大的乘积和

参考博客:http://blog.csdn.net/linhuanmars/article/details/39537283

public int maxProduct(int[] A) {  
    if(A==null || A.length==0)  
        return 0;  
    if(A.length == 1)  
        return A[0];  
    int max_local = A[0];  
    int min_local = A[0];  
    int global = A[0];  
    for(int i=1;i<A.length;i++)  
    {  
        int max_copy = max_local;  
        max_local = Math.max(Math.max(A[i]*max_local, A[i]), A[i]*min_local);  
        min_local = Math.min(Math.min(A[i]*max_copy, A[i]), A[i]*min_local);  
        global = Math.max(global, max_local);  
    }  
    return global;  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
解题思路: 题目要求我们寻找一个最短的子数组,使得删去它之后原数组变成非递减数组。那么我们可以考虑贪心策略。首先,我们需要找到最长的非递减子数组,这个子数组在最后的答案中肯定是不会被删除的,因为删去这个子数组回导致整个数组非递减性质被破坏。接着我们假设这个子数组的右端点为 i(当然我们还不知道实际的值是多少),那么我们接着考虑如何从左边找到最短的子数组,使得删去这个子数组之后原数组变为非递减数组。假设我们找到了左端点为 j 的子数组,那么这个子数组的长度就是 i-j-1。然后我们可以用一个变量 cnt 来统计需要从这个子数组中删去的数字的个数,这个变量的初始化值为 0,每当我们找到一个子数组的边界,而这个子数组又不是非递减的时候,我们就将这个子数组中从小到大排列的数字删掉并且让 cnt++。最终答案就是 i-j-1-cnt,即最长的非递减子数组长度减去从左边找到的最短需要删除的子数组的长度再减去被删除的数字个数。 具体实现可以使用单调栈,单调栈里存的是数组元素的下标,栈顶到栈底位置对应的元素值是单调不降的。遍历数组的时候,如果当前元素比单调栈的栈顶小,说明需要找到右端点,于是不断pop出深度直到栈顶元素小于当前元素或者栈空,此时当前元素的下标就是右端点。接着我们在单调栈里寻找左端点,这里需要注意我们需要从右往左遍历单调栈,因为要保证最先找到的左端点一定是在右端点左边的。用一个变量 cnt 统计需要删除的元素个数,最终计算答案得到结果。 时间复杂度:O(n),两次单调栈遍历,最差情况下遍历整个数组。空间复杂度:O(n),单调栈中的元素个数最大为 n。 代码:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值