[Leedcode][JAVA][第152题][乘积最大子数组][动态规划]
【问题描述】[中等]
给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。示例 1:输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
示例 2:输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
【解答思路】
1. 动态规划
时间复杂度:O(N) 空间复杂度:O(N)
public class Solution {public int maxProduct(int[] nums) {int len = nums.length;if (len == 0) {return 0;}// dp[i][0]:以 nums[i] 结尾的连续子数组的最小值// dp[i][1]:以 nums[i] 结尾的连续子数组的最大值int[][] dp = new int[len][2];dp[0][0] = nums[0];dp[0][1] = nums[0];for (int i = 1; i < len; i++) {if (nums[i] >= 0) {dp[i][0] = Math.min(nums[i], nums[i] * dp[i - 1][0]);dp[i][1] = Math.max(nums[i], nums[i] * dp[i - 1][1]);} else {dp[i][0] = Math.min(nums[i], nums[i] * dp[i - 1][1]);dp[i][1] = Math.max(nums[i], nums[i] * dp[i - 1][0]);}}// 只关心最大值,需要遍历int res = dp[0][1];for (int i = 1; i < len; i++) {res = Math.max(res, dp[i][1]);}return res;}
}
2. 动态规划优化 表格复用
时间复杂度:O(N) 空间复杂度:O(1)
public class Solution {public int maxProduct(int[] nums) {int len = nums.length;if (len == 0) {return 0;}int preMax = nums[0];int preMin = nums[0];// 滚动变量int curMax;int curMin;int res = nums[0];for (int i = 1; i < len; i++) {if (nums[i] >= 0) {curMax = Math.max(preMax * nums[i], nums[i]);curMin = Math.min(preMin * nums[i], nums[i]);} else {curMax = Math.max(preMin * nums[i], nums[i]);curMin = Math.min(preMax * nums[i], nums[i]);}res = Math.max(res, curMax);// 赋值滚动变量preMax = curMax;preMin = curMin;}return res;}
}
class Solution {public int maxProduct(int[] nums) {int max = Integer.MIN_VALUE, imax = 1, imin = 1; //一个保存最大的,一个保存最小的。for(int i=0; i<nums.length; i++){if(nums[i] < 0){ int tmp = imax; imax = imin; imin = tmp;} //如果数组的数是负数,那么会导致最大的变最小的,最小的变最大的。因此交换两个的值。imax = Math.max(imax*nums[i], nums[i]);imin = Math.min(imin*nums[i], nums[i]);max = Math.max(max, imax);}return max;}
}
【总结】
1.无后效性
无后效性是指如果在某个阶段上过程的状态已知,则从此阶段以后过程的发展变化仅与此阶段的状态有关,而与过程在此阶段以前的阶段所经历过的状态无关。利用动态规划方法求解多阶段决策过程问题,过程的状态必须具备无后效性
「动态规划」通常不关心过程,只关心「阶段结果」,这个「阶段结果」就是我们设计的「状态」。什么算法关心过程呢?「回溯算法」,「回溯算法」需要记录过程,复杂度通常较高。
而将状态定义得更具体,通常来说对于一个问题的解决是满足「无后效性」的。这一点的叙述很理论化,不熟悉朋友可以通过多做相关的问题来理解「无后效性」这个概念。
2.做题通常可以不先考虑优化空间
- 空间通常来说是用户不敏感的,并且在绝大多数情况下,空间成本低,我们写程序通常需要优先考虑时间复杂度最优;
- 时间复杂度和空间复杂度通常来说不可能同时最优,所以我们经常看到的是优化解法思路都是「空间换时间」,这一点几乎贯穿了基础算法领域的绝大多数的算法设计思想;
- 限制空间的思路,通常来说比较难,一般是在优化的过程中才考虑优化空间,在一些限制答题时间的场景下(例如面试),先写出一版正确的代码是更重要的,并且不优化空间的代码一般来说,可读性和可解释性更强。
3.动态规划总结
动态规划问题通常用于计算多阶段决策问题的最优解。
多阶段,是指解决一个问题有多个步骤;
最优解,是指「最优子结构」。
动态规划有三个概念很重要:
重复子问题:因为重复计算,所以需要「空间换时间」,记录子问题的最优解;
最优子结构:规模较大的问题的最优解,由各个子问题的最优解得到;
无后效性(上面已经解释)。
动态规划有两个特别关键的步骤:
设计状态:
- 有些题目问啥,就设计成什么;
- 如果不行,只要有利于状态转移,很多时候,就可以设计成状态;
- 根据过往经验;
- 还有一部分问题是需要在思考的过程中调整的,例如本题。
**推导状态转移方程:**通常是由问题本身决定的。
动态规划问题思考的两个方向:
- 自顶向下:即「递归 + 记忆化」,入门的时候优先考虑这样做;
- 自底向上:即「递归」,从一个最小的问题开始,逐步得到最终规模问题的解。后面问题见得多了,优先考虑这样做,绝大部分动态规划问题可以「自底向上」通过递推得到。
转载链接:https://leetcode-cn.com/problems/maximum-product-subarray/solution/dong-tai-gui-hua-li-jie-wu-hou-xiao-xing-by-liweiw/
[Leedcode][JAVA][第152题][乘积最大子数组][动态规划]相关推荐
- [Leedcode][JAVA][第300题][最长上上子序列][动态规划][压缩空间]
[问题描述][中等] 给定一个无序的整数数组,找到其中最长上升子序列的长度.示例:输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,101],它 ...
- [Leedcode][JAVA][第887题][鸡蛋掉落][谷歌面试][动态规划]
[问题描述] [887. 鸡蛋掉落] 你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N 共有 N 层楼的建筑.每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去.你知道存在楼层 F ,满足 ...
- [Leedcode][JAVA][第22题括号生成][DFS][BFS][动态规划]
[问题描述]22. 括号生成 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合. 示例:输入:n = 3 输出:["((()))",&q ...
- leetcode算法题--乘积最大子数组
原题链接:https://leetcode-cn.com/problems/maximum-product-subarray/ 思路是用两个数组,一个最大max[],一个最小min[].然后用动态规划 ...
- [Leedcode][JAVA][第15题][三数之和][数组][双指针]
[问题描述][中等] 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组.注意:答案中 ...
- [Leedcode][JAVA][第1014题][最佳观光组合][数组][暴力优化]
[问题描述][中等] 给定正整数数组 A,A[i] 表示第 i 个观光景点的评分,并且两个景点 i 和 j 之间的距离为 j - i.一对景点(i < j)组成的观光组合的得分为(A[i] + ...
- [Leedcode][JAVA][第33题][搜索旋转排序数组]
[问题描述][33. 搜索旋转排序数组] [中等] 假设按照升序排序的数组在预先未知的某个点上进行了旋转.( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). ...
- [Leedcode][JAVA][第466题][统计重复个数][数组]
[问题描述]466. 统计重复个数 由 n 个连接的字符串 s 组成字符串 S,记作 S = [s,n].例如,["abc",3]="abcabcabc".如果 ...
- [Leedcode][JAVA][第105题][从前序与中序遍历序列构造二叉树][栈][递归][二叉树]
[问题描述][中等] 根据一棵树的前序遍历与中序遍历构造二叉树.注意: 你可以假设树中没有重复的元素.例如,给出前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = ...
最新文章
- 2018年薪资最高的15个技术岗
- vs2005打开vs2008
- Web Service 学习笔记(2)
- android根据mac地址连接耳机,Android获取设备IMEI和Mac地址
- VS2019调试查看变量_你很可能需要知道这个调试小技巧
- python读取csv文件坐标地图描点_python3 通过百度地图API获取城市POI点并存于CSV格式...
- grid.getSelectionModel的所有操作
- 设备的开发【WP7学习札记之五】
- 深入理解 flex 布局以及计算_Flexbox, Layout
- jQuery实现点击显示和隐藏内容
- PDF文件密码破解方法有几种,快来看!
- 基于html的明星网站
- 查找算法——adjacent_find
- 多线程应用_左圆右方
- K空间的理解 倒空间
- 第39级台阶回溯算法c语言,五大经典算法之回溯法 - osc_9ipdey7e的个人空间 - OSCHINA - 中文开源技术交流社区...
- ObjectUtils.isEmpty() 和 null 区别
- 离线数据系统之MapReduce加强
- chevkv基于成对ANI的快速基因组聚类
- SciTe 中文设置(解决乱码,中文界面)