首页 > 其他分享 >力扣-152-乘积最大的子数组

力扣-152-乘积最大的子数组

时间:2022-11-03 17:11:56浏览次数:94  
标签:152 乘积 nums int max maxP 力扣 minRecord dp

对于dp[i],

  • 如果nums[i-1]>0,dp[i-1]也>0,那就是dp[i-1]*nums[i-1]
  • 如果<0,>0,那就是nums[i-1]
  • 0,<0,那就是nums[i-1]

  • <0,<0,那就是dp[i-1]*nums[i-1]

同样参考最大子数和,还需要一个额外变量来记录最大的…

int maxProduct(vector<int>& nums) {
	int n = nums.size(),maxP = -11;
	vector<int> dp(n+1);
	dp[0] = 1;
	for (int i = 1; i <= n; i++) {
		int temp = nums[i - 1] * dp[i - 1];
		if (temp > 0) dp[i] = temp;
		else dp[i] = nums[i - 1];
		maxP = max(maxP, dp[i]);
	}
	return maxP;
}

但是这么做是错误的,就比如-2,3,-4这个例子,最后以-4结尾的子数组最大乘积是24,而不是-4
它参考的不是上一步的最优解3,而是-2和3的乘积-6,也就是说至少这么照搬定义是不符合“最优子结构”的

瞄了题解的提示

这样定义,关键在于对nums[i-1]正负性的讨论,

  • 如果nums[i-1]>0,那么我们期望结果最大的话,就希望前面最大的正数乘积
  • 如果nums[i-1]<0,那么就期望前面最小的负数乘积
int maxProduct(vector<int>& nums) {
	int n = nums.size(),maxP = -11;
	vector<int> dp(n+1),minRecord(n+1);
	dp[0] = 1,minRecord[0]=1;
	for (int i = 1; i <= n; i++) {
		if (nums[i - 1] > 0) {
			minRecord[i] = min(nums[i - 1], minRecord[i - 1] * nums[i - 1]);
			dp[i] = max(dp[i - 1] * nums[i - 1], nums[i - 1]);
		}
		else {
			minRecord[i] = min(nums[i - 1], dp[i - 1] * nums[i - 1]);
			dp[i] = max(nums[i - 1] * minRecord[i - 1], nums[i - 1]);
		}
		maxP = max(maxP, dp[i]);
	}

	return maxP;
}

这里其实维护了两个dp数组,最大就是我们要要的,只需要再维护一个最小
然后众所周知,一维dp可以空间优化

int maxProduct(vector<int>& nums) {
	// 前面赋初值11是不合理的
	// 这里的三个nums[0]初值其实都是没必要的,但循环遍历nums是必要的
	int maxP = nums[0];
	int maxRecord = nums[0], preMax = 1, minRecord = nums[0], preMin = 1;
	for (int i = 0; i < nums.size(); i++) {
		if (nums[i] > 0) {
			minRecord = min(nums[i], preMin * nums[i]);
			maxRecord = max(preMax * nums[i], nums[i]);
		}
		else {
			minRecord = min(nums[i], preMax * nums[i]);
			maxRecord = max(nums[i] * preMin, nums[i]);
		}
		preMax = maxRecord;
		preMin = minRecord;
		maxP = max(maxP, maxRecord);
	}
	return maxP;
}

本题的关键在于需要一个额外的dp辅助数组,本题是经典最大字数和的变形

标签:152,乘积,nums,int,max,maxP,力扣,minRecord,dp
From: https://www.cnblogs.com/yaocy/p/16855100.html

相关文章

  • 力扣 二叉树 算法+题目 整理
    二叉树基础包括三种遍历,建树和遍历的方法。二叉树遍历力扣144,94,145二叉树前中后序遍历使用递归或者迭代空间复杂度都是o(n),而通过morris遍历则可以达到o(1),其介绍......
  • 力扣1668(java&python)-最大重复子字符串(简单)
    题目:给你一个字符串 sequence ,如果字符串word 连续重复 k 次形成的字符串是 sequence 的一个子字符串,那么单词 word的重复值为k。单词word 的最大重复值......
  • 力扣 257. 二叉树的所有路径
    257.二叉树的所有路径给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。叶子节点是指没有子节点的节点。示例1:输入:root=[1......
  • 力扣 129. 求根节点到叶节点数字之和
    129.求根节点到叶节点数字之和给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字。每条从根节点到叶节点的路径都代表一个数字:例......
  • 力扣-147-对链表进行插入排序
    ListNode*insertionSortList(ListNode*head){ //待排节点需要和它前面的节点比较?单链表怎么比,单链表的反向遍历? //只能从头开始找 //还要手写链表的交换? if(!he......
  • 力扣 124. 二叉树中的最大路径和 [1.0,2.0]
    124.二叉树中的最大路径和路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 ......
  • 力扣 113. 路径总和 II [dfs,bfs]
    113.路径总和II给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。叶子节点是指没有子节......
  • 力扣409(java&python)-最长回文串(简单)
    题目:给定一个包含大写字母和小写字母的字符串 s ,返回 通过这些字母构造成的最长的回文串 。在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串......
  • 力扣 112. 路径总和
    112.路径总和给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标......
  • 力扣HOT100算法题5:最长回文字串
    文章目录​​一、题目​​​​二、方法一:解题思路​​​​三、方法一:代码解析​​​​四、方法二:动态规划​​​​五、方法二:代码解析​​一、题目给你一个字符串s,找到s......