博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
leetcode----152. Maximum Product Subarray
阅读量:4112 次
发布时间:2019-05-25

本文共 2871 字,大约阅读时间需要 9 分钟。

链接:

大意:

给定一个整型数组nums,数组中元素可正可负可为0.要求找出一个连续子数组,使得该子数组是所有子数组中各元素最大,返回最大的乘积。例子:

思路:

一开始感觉应该用动态规划来做,但是递推方程式始终没想出来。于是只能老老实实地做了...

首先使用一个列表 zeros记录数组中所有0所在的位置,在遍历数组时,主要做两个事:

  1. 记录当前的乘积max(从nums[0]到nums[i])
  2. 若当前元素为0,则将当前位置add到zeros

第一次遍历完之后,首先判断max是否大于0.

  1. 若max大于0,则可以直接返回max了
  2. 若max<=0并且zeros.size()==0,也就是数组中没有0,但是肯定有负数(不然max怎么可能小于0)。那么对于整个数组,找到第一个正数到一个负数之间(包含首尾)的乘积negVOne以及最后一个负数到最后一个正数之间(包含首尾)的乘积negVLast。对于整个区间的成绩v,返回 Math.max(v / negVOne, v / negVLast)

若上面的情况都不满足,也就是max<0并且数组中含有元素0.则需要针对元素0的位置,对数组进行分段,依次求得每一段的最大连续子数组乘积,再比较返回最大的乘。(在代码中即为helper函数)

代码:

class Solution {    public int maxProduct(int[] nums) {        if (nums.length == 0)            return 0;        int max = 1, i = 0;        ArrayList
zeros = new ArrayList<>(); // 存储所有0的位置 for (int num : nums) { max *= num; if (num == 0) zeros.add(i); i++; } if (max > 0) return max; else if (zeros.size() == 0) return helper(nums, 0, nums.length - 1); max = 0; int s = 0; // 通过元素0 将原数组分成n段 for (int e : zeros) { max = Math.max(helper(nums, s, e - 1), max); s = e + 1; } max = Math.max(helper(nums, s, nums.length - 1), max); return max; } public int helper(int[] nums, int s, int e) { if (s == e) return nums[s]; if (s > e) return Integer.MIN_VALUE; int negOne = -1, negLast = -1; // 记录当前段中第一个和最后一个负数的位置 int negVOne = 1, negVLast = 1; // 记录第一个负数左边的乘积(包括负数) 和 最后一个负数右边的乘积(包括负数) int v = 1; while (s <= e) { if (negOne == -1) { // 还未找到第一个负数 negVOne *= nums[s]; } else if (negLast != -1) // 已找到除第一个负数之外的另一个负数 negVLast *= nums[s]; if (nums[s] < 0) { if (negOne == -1) { negOne = negLast = s; } else { negLast = s; } negVLast = nums[s]; } v *= nums[s]; // v只管乘 s++; } if (v > 0) return v; return Math.max(v / negVOne, v / negVLast); }}

结果:

结论:

仍然感觉得用动态规划好些,虽然这个解法 时间复杂度为 O(n),空间复杂度为O(n)。 但是用动态规划应该会更好看。

最佳:(动态规划)

class Solution {    // 若最终的结果小于0 则表明有奇数个负数 需要干掉一段负数(可能附带正数) 被干掉的肯定是第一段或者最后一段    public int maxProduct(int[] nums) {        if(nums == null || nums.length ==0) return 0;        int max = nums[0];        int currMax = 1;        for(int i =0; i< nums.length ;i++){            currMax *= nums[i];            if(currMax > max) max=currMax;            if(currMax ==0) currMax =1; // 遇到0则重新开始        }                currMax = 1;        for(int i =nums.length-1; i >=0 ;i--){            currMax *= nums[i];            if(currMax > max) max=currMax;                if(currMax ==0) currMax =1; // 遇到0则重新开始        }                return max;    }}

 

转载地址:http://exesi.baihongyu.com/

你可能感兴趣的文章
【git】git的origin和master分析
查看>>
Golang 新手可能会踩的 50 个坑-值得一看,强力推荐
查看>>
ubuntu安装opendr
查看>>
C++ 实现多线程:生产者消费者模型
查看>>
python 利用 vispy 读取显示 .obj文件
查看>>
ubuntu16 install LaTeX
查看>>
Ubuntu16.04进入不了图形界面 :the system is running in low-graphics mode
查看>>
Anaconda 搭建python3.5 开发环境
查看>>
Linux基础系列-定时器与时间管理
查看>>
Linux基础系列-可执行程序的产生过程
查看>>
Linux基础系列-Kernel 初始化宏
查看>>
Linux子系统系列-I2C
查看>>
元旦前
查看>>
2010远去了
查看>>
音乐与代码
查看>>
Linux基础系列-DEBUG
查看>>
Linux基础系列-信号及信号处理
查看>>
Think more, do more!
查看>>
Linux子系统系列-时钟子系统
查看>>
六一悄悄的过了
查看>>