LeetCode HOT 100:乘积最大子数组(动态规划)
题目:152. 乘积最大子数组
题目描述:
给你一个整数数组,在该数组的所有子数组中,找到一个子数组中所有元素相乘积最大,返回这个最大的积。子数组就是一个数组中,由一个或几个下标连续的元素,组成的小数组,就叫原数组的子数组。
思路:
这一题和题目:53. 最大子数组和很像。但是又复杂了一点。所以建议先搞懂53题,再来看这道题。在53题曾经说过求子数组问题,都可以向一种思维上靠拢。即以某一个元素为结尾的子数组中,得到一个结果。然后以每一个元素都作为结尾,得到很多个结果,然后在这些结果中进行比较,一定得到正确的结果。
而本题和加法又不太一样,加法比如说想找到以每一个元素为结尾的子数组的最大和,只需要前一个元素为结尾的子数组最大和能拿到,就可以得到该元素为结尾的子数组的最大和。
举个例子:加法中,数组为nums
,想要得到下标i
为结尾的子数组的最大和X
,只需要得到下标i-1
为结尾的子数组的最大和Y
,然后选择要不要加上nums[i]
就可以得到了。即 X = Math.max(nums[i], Y + nums[i])
。即最大值只会出现在nums[i]
和Y + nums[i]
中选择。
但是乘法不一样,乘法会有负负得正。乘积最大值,不仅会出现在nums[i]
、Y * nums[i]
中。如果nums[i]
是负值,下标i-1
为结尾的子数组的最小乘积M
,nums[i] * M
也可能是乘积最大值。
举个例子:[100, 6, -2, -3]
,以-3
结尾的子数组的最大乘积就是-3 * -1200(以-2为结尾的子数组的最小乘积) = 3600
。
所以,乘积需要得到两个结果,以某一下标结尾的子数组中最大乘积以及最小乘积。
步骤:
1、初始化动态规划数组,以0
下标结尾的子数组最大乘积、最小乘积都是nums[0]
本身
2、在循环中,通过i - 1
的最大乘积和最小乘积,结合公式,得到三条数据,三者进行比较,得到i
的最大乘积和最小乘积,更新dp
数组,以及判断最大乘积是否需要更新
3、循环结束后,返回最大乘积
代码:
未优化空间的动态规划版本
public int maxProduct(int[] nums) {
int n = nums.length;
int[] dpMax = new int[n];
int[] dpMin = new int[n];
// 记录以 0 为结尾的子数组的最大累乘积和最小累乘积
dpMax[0] = nums[0];
dpMin[0] = nums[0];
int ans = nums[0];
for (int i = 1; i < nums.length; i++) {
// 记录三种可能性
int p1 = nums[i];
int p2 = nums[i] * dpMax[i - 1];
int p3 = nums[i] * dpMin[i - 1];
// 从三种可能性中取最大累乘积和最小累乘积
int curMax = Math.max(p1, Math.max(p2, p3));
int curMin = Math.min(p1, Math.min(p2, p3));
// 将最大累乘积与ans比较
ans = Math.max(ans, curMax);
// 更新以 i 为结尾的子数组的最大累乘积和最小累乘积
dpMax[i] = curMax;
dpMin[i] = curMin;
}
return ans;
}
空间优化代码
// 因为dp[i]只和dp[i - 1]有关,所以可以优化空间
public int maxProduct(int[] nums) {
// 记录以 0 为结尾的子数组的最大累乘积
int preMax = nums[0];
// 记录以 0 为结尾的子数组的最小累乘积
int preMin = nums[0];
int ans = nums[0];
for (int i = 1; i < nums.length; i++) {
// 记录三种可能性
int p1 = nums[i];
int p2 = nums[i] * preMax;
int p3 = nums[i] * preMin;
// 从三种可能性中取最大累乘积和最小累乘积
int curMax = Math.max(p1, Math.max(p2, p3));
int curMin = Math.min(p1, Math.min(p2, p3));
// 将最大累乘积与ans比较
ans = Math.max(ans, curMax);
// 更新以 i 为结尾的子数组的最大累乘积和最小累乘积
preMax = curMax;
preMin = curMin;
}
return ans;
}
LeetCode HOT 100:乘积最大子数组(动态规划)的更多相关文章
- [LeetCode] 53. Maximum Subarray 最大子数组 --动态规划+分治
Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...
- LeetCode HOT 100:最大子数组和
题目:53. 最大子数组和 题目描述: 给你一个整数数组,在该数组的所有子数组中,找到一个子数组中所有元素相加和最大,返回这个最大的和.子数组就是一个数组中,由一个或几个下标连续的元素,组成的小数组, ...
- leetcode 刷题(数组篇)152题 乘积最大子数组 (动态规划)
题目描述 给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积. 示例 1: 输入: [2,3,-2,4] 输出: 6 解释: 子 ...
- 1. 线性DP 152. 乘积最大子数组
152. 乘积最大子数组 https://leetcode-cn.com/problems/maximum-product-subarray/ func maxProduct(nums []int) ...
- [LeetCode] 53. Maximum Subarray 最大子数组
Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...
- [leetcode]53. Maximum Subarray最大子数组和
Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...
- Leetcode题目152.乘积最大子序列(动态规划-中等)
题目描述: 给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数). 示例 1: 输入: [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] 有最大乘积 6 ...
- LeetCode HOT 100:在排序数组中查找元素的第一个和最后一个位置
题目:34. 在排序数组中查找元素的第一个和最后一个位置 题目描述: 给你一个递增数组,和一个目标值target,最终返回数组中第一次出现target和最后一次出现target的下标.如果该数组中没有 ...
- LeetCode Top 100 Liked 点赞最高的 100 道算法题
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:刷题顺序,刷题路径,好题,top100,怎么刷题,Leet ...
- [LeetCode] Maximum Product Subarray 求最大子数组乘积
Find the contiguous subarray within an array (containing at least one number) which has the largest ...
随机推荐
- 2018 Web开发人员学习路线图
以下 Web 开发人员学习路线图是来自 Github developer-roadmap 项目,目前已经有繁体版翻译 developer-roadmap-chinese. 主要有三个方向,分别为前端开 ...
- Dubbo-聊聊Dubbo协议
前言 Dubbo源码阅读分享系列文章,欢迎大家关注点赞 SPI实现部分 Dubbo-SPI机制 Dubbo-Adaptive实现原理 Dubbo-Activate实现原理 Dubbo SPI-Wrap ...
- nestjs搭建HTTP与WebSocket服务
最近在做一款轻量级IM产品,后端技术栈框架使用了nodejs + nestjs作为服务端.同时,还需要满足一个服务同时支持HTTP服务调用以及WebSocket服务调用,此文主要记录本次搭建过程,以及 ...
- fbterm的配置,纯文本终端显示中文
安装 fbterm sudo apt-get install fbterm 设置普通用户可以执行 fbterm 命令 sudo adduser username video #username为用户名 ...
- PostgreSQL:查询元数据(表 、字段)信息、库表导入导出命令
一.查询表.模式及字段信息 1.查询指定模式下的所有表 select tablename,* from pg_tables where schemaname = 'ods'; 2.查询指定模式下的表名 ...
- 【基础语法规范】【函数式编程、字符串分割】BC6:输出输入的第二个整数
思路:数组or字符串split分割 一.Scala 方法1:Int数组[不行] import scala.io.StdIn object Main{ def main(args:Array[Strin ...
- 【每日一题】【快慢指针相遇】2022年1月25日-NC3 链表中环的入口结点
描述给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null. 答案: /* public class ListNode { int val; ListNode next = ...
- jupyter 数据显示设置
#设置显示行数pd.set_option('display.max_row',None)#设置显示列数pd.set_option('display.max_column',None)#设置显示宽度pd ...
- [数据结构]哈希拉链法化解冲突+ASL计算
看这篇就好(自用,别骂我) 摘自博客园 存疑:学校考试空节点算不算查找次数???
- 深入理解 MySQL 的事务隔离级别和 MVCC 机制
前言 我们都知道 MySQL 实现了 SQL 标准中的四个隔离级别,但是具体是如何实现的可能还一知半解,本篇博客将会从代码层面讲解隔离级别的实现方式,下面进入正题. 事务 考虑这样一个场景:博主向硝子 ...