152-乘积最大子数组-又是典型的DP

题目

核心思路

这道题是一道很典型DP问题,直接穷举所有可能的子数组会发现有很多重复计算的部分,同时子数组的最大乘积是有最优的子结构的,因此可以考虑到使用DP方法来解决。
在乘法中有两种比较特殊的值 负数0,遇到0会使得总的乘积直接变成0,而遇到负数会使得最大值直接变成最小值,因此我们需要用两个数组来保存遍历到i位置的最大值imax[i]和最小值imin[i],然后对负数分类讨论就可以解决负数的问题了。
然后来看0这个特殊元素,由于题目中提到子数组可以是单个元素,那么遇到任意一个元素,都要同时将之前乘积与本元素做比较来存入imaximin,这样在遇到0的时候,要么取前边的乘积乘以0、要么直接取本元素0,直接将这种可能包括其中了,即:

            if(nums[i - 1] < 0){
                imax[i] = Math.max(imin[i - 1] * nums[i - 1], nums[i - 1]);
                imin[i] = Math.min(imax[i - 1] * nums[i - 1], nums[i - 1]);
            }else{
                imax[i] = Math.max(imax[i - 1] * nums[i - 1], nums[i - 1]);
                imin[i] = Math.min(imin[i - 1] * nums[i - 1], nums[i - 1]);
            }

这样得到的每个imax[i]都是可能的最大值,所以每次循环取一次最大值:

max = Math.max(max, imax[i]);

接下来就是分析递推公式,优化空间复杂度了。容易发现,imaximin都只与他们的上一个值相关,因此,可以将空间优化为O(1),仅使用两个变量来表示这两个值,即:

            if(nums[i - 1] < 0){
                imax = Math.max(imin * nums[i - 1], nums[i - 1]);
                imin = Math.min(imax * nums[i - 1], nums[i - 1]);
            }else{
                imax = Math.max(imax * nums[i - 1], nums[i - 1]);
                imin = Math.min(imin * nums[i - 1], nums[i - 1]);
            }

代码看起来还是很繁琐,上下的 if和else 部分只是换了imaximin,表达式其他的地方一模一样,那么我们可以在遇到负数的时候交换imaximin,然后去做计算,也就能让代码看着简洁一些。

完整代码

class Solution {
    public int maxProduct(int[] nums) {
        int imax = 1, imin = 1, max = Integer.MIN_VALUE;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] < 0) {
                int temp = imax;
                imax = imin;
                imin = temp;
            }

            imax = Math.max(imax * nums[i], nums[i]);
            imin = Math.min(imin * nums[i], nums[i]);
            max = Math.max(max, imax);
        }
        return max;
    }
}

找递推公式还是很需要锻炼的,自己还是差的很多啊。另笔者也是在学习中,如果有写的不对的地方还请指出,感恩相遇~

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Maximum Product Subarray 标签(空格分隔): algorithm 涉及到公式请到作业部落查...
    别时茫茫阅读 5,222评论 0 0
  • 动态规划(DP) 1.最大子序和(leetcode 53 S.) 给定一个整数数组 nums ,找到一个具有最大...
    不入大厂不改名阅读 4,474评论 0 2
  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 9,161评论 0 2
  • 数组在程序设计中,为了处理方便, 把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类数据元素的集合称...
    朱森阅读 9,610评论 2 13
  • 326. Power of Three Given an integer, write a function to...
    跑者小越阅读 6,490评论 0 1

友情链接更多精彩内容