输入一个长度为n的整型数组nums,数组中的一个或连续多个整数组成一个子数组。求所有子数组的乘积的最大值。
1.子数组是连续的,且最小长度为1,最大长度为n
2.长度为1的子数组,乘积视为其本身,比如[4]的乘积为4
3.该题的数据保证最大的乘积不会超过int的范围,即不超过
数据范围:
[3,2,-1,4]
6
子数组[3,2]的乘积为6,[3,2,-1,4]的乘积为-24,[4]的乘积为4,故返回6
[-3,0,-2]
0
因为0在中间,所有包含0的子数组的乘积都为0,另外的数都是负数,所以最大乘积的子数组为[0],返回为0,因为子数组要求是连续的,所以[-3,-2]不是[-3,0,-2]的子数组,所以不能为6,
[-3,2,-2]
12
//max是以i结尾的最大乘积 min是以i结尾的最小乘积 public static int maxProduct(int[] nums) { int max = nums[0]; int min = nums[0]; int result = nums[0]; for (int i = 1; i < nums.length; i++) { int t =max; max = Math.max(nums[i], Math.max(max * nums[i], min * nums[i])); min = Math.min(nums[i], Math.min(t * nums[i], min * nums[i])); result = Math.max(result,max); } return result; }
public static int maxProduct(int[] nums) { // write code here int len = nums.length; if (len == 1) return nums[0]; // 表示 i 到 j 的最大乘积, i > j int[][] dp = new int[len + 1][len + 1]; // 初始化第一行 dp[1][1] = nums[0]; int res = nums[0]; for (int i = 2; i <= len; i++) { dp[1][i] = dp[1][i - 1] * nums[i - 1]; res = Math.max(res, dp[1][i]); } // 开始动态规划计算 i 到 j 的连续数组的最大乘积 for (int i = 2; i <= len; i++) { for (int j = i; j <= len; j++) { if (i == j){ dp[i][j] = nums[i - 1]; res = Math.max(res, dp[i][j]); } else if (i < j) { dp[i][j] = dp[i][j - 1] * nums[j - 1]; res = Math.max(res, dp[i][j]); } } } return res; }正确解法:
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param nums int整型一维数组 * @return int整型 */ public static int maxProduct(int[] nums) { int len = nums.length; if (len == 1) return nums[0]; int[] maxDp = new int[len]; int[] minDp = new int[len]; maxDp[0] = nums[0]; minDp[0] = nums[0]; int res = nums[0]; for (int i = 1; i < len; i++) { // 1. nums[i] 本身也是一个子序列 // 2. 最大值乘以当前值可能为最大值(当前为正) // 3. 最小值乘以当前值可能为最大值(当前为负) maxDp[i] = Math.max(nums[i], Math.max(maxDp[i - 1] * nums[i], minDp[i - 1] * nums[i])); minDp[i] = Math.min(nums[i], Math.min(maxDp[i - 1] * nums[i], minDp[i - 1] * nums[i])); res = Math.max(res, maxDp[i]); } return res; } }
// 从左往右一直累乘,记录最大值,遇到0后从1开始。同样的方式可以从右往左进行。 public int maxProduct (int[] nums) { long res = nums[0]; long m = 1; for (int i = 0; i < nums.length; i++) { m = m * nums[i]; res = Math.max(res, m); if (m == 0) { m = 1; } } m = 1; for (int i = nums.length - 1; i >= 0; i--) { m = m * nums[i]; res = Math.max(res, m); if (m == 0) { m = 1; } } return (int)res; }时间复杂度:O(n) 空间复杂度 O(1)
public int maxProduct (int[] nums) { // write code here if (nums.length < 2) return nums[0]; int res = nums[0]; int dp = 1; for (int i = 0; i < nums.length; i++) { dp = dp * nums[i]; res = Math.max(res, dp); if (dp == 0) { dp = 1; } } //先正序遍历一遍,此时会出现如果两个连续负数导致结果遗漏问题 //例如6,9,-3,-7,8,0,-1,6 //所以再逆序遍历一遍进行结果检查 dp = 1; for (int i = nums.length - 1; i >= 0; i--) { dp = dp * nums[i]; res = Math.max(res, dp); if (dp == 0) { dp = 1; } } return res; }
public int maxProduct (int[] nums) { // write code here int len=nums.length ,res=nums[0]; int[] maxArr=new int[len] ,minArr=new int[len]; maxArr[0]=nums[0]; minArr[0]=nums[0]; for(int i=1;i<len;i++){ maxArr[i]=Math.max(Math.max(nums[i] ,maxArr[i-1]*nums[i]) ,minArr[i-1]*nums[i]); minArr[i]=Math.min(Math.min(nums[i] ,maxArr[i-1]*nums[i]) ,minArr[i-1]*nums[i]); res=Math.max(maxArr[i] ,res); } return res; }
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param nums int整型一维数组 * @return int整型 */ public int maxProduct (int[] nums) { // write code here // dp[i] 数组0 - i的以i结尾的子数组的最大乘积,但是dp[i]既有可能从max转移过来,也有可能从最小的负数转移过来 int len = nums.length; int[] dpMax = new int[len]; int[] dpMin = new int[len]; dpMax[0] = nums[0]; dpMin[0] = nums[0]; int max = nums[0]; for(int i = 1; i < len; i++) { dpMax[i] = Math.max(nums[i], Math.max(dpMax[i - 1] * nums[i], dpMin[i - 1] * nums[i])); dpMin[i] = Math.min(nums[i], Math.min(dpMax[i - 1] * nums[i], dpMin[i - 1] * nums[i])); max = Math.max(dpMax[i], max); } return max; } }
class Solution { public: /** * 当前元素为0,那么以当前元素结尾的子数组的最大乘积为0,即本身。 * 当前元素不为0,累乘到当前元素可能为正,也可能为负,也可能是 * 当前元素本身。 * 记录累乘最大值、最小值然后递推下一个元素,并使用 * 变量维护已知的最大乘积。 */ int maxProduct(vector<int>& nums) { int res = nums[0]; int pre_pos = 1; int pre_neg = 1; for (int i = 0; i < nums.size(); i++) { pre_pos *= nums[i]; pre_neg *= nums[i]; int temp = max(nums[i], max(pre_pos, pre_neg)); pre_neg = min(nums[i], min(pre_pos, pre_neg)); pre_pos = temp; res = max(res, pre_pos); } return res; } };
package main import _"fmt" /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param nums int整型一维数组 * @return int整型 */ func maxProduct( nums []int ) int { pre1,pre2,ans:=nums[0],nums[0],nums[0] for _,x:=range nums[1:]{ tmp:=pre1 pre1=max(max(pre1*x,pre2*x),x) pre2=min(min(tmp*x,pre2*x),x) if pre1>ans{ ans=pre1 } } return ans } func max(a,b int)int{ if a>b{ return a } return b } func min(a,b int)int{ if a>b{ return b } return a }
class Solution { public int maxProduct(int[] nums) { if (nums ==null || nums.length==0) return 0; int res=nums[0]; int pre_max=nums[0]; int pre_min=nums[0]; for (int i=1;i<nums.length;i++){ int cur_max=Math.max(Math.max(pre_max*nums[i],pre_min*nums[i]),nums[i]); int cur_min=Math.min(Math.min(pre_max*nums[i],pre_min*nums[i]),nums[i]); res=Math.max(res,cur_max); pre_max=cur_max; pre_min=cur_min; } return res; } }
# -*- coding: utf-8 -*- # # 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 # # # @param nums int整型一维数组 # @return int整型 # class Solution: """ 题目: https://www.nowcoder.com/practice/abbec6a3779940aab2cc564b22d36859?tpId=196&tqId=37119&rp=1&ru=/exam/oj&qru=/exam/oj&sourceUrl=%2Fexam%2Foj%3FjudgeStatus%3D3%26page%3D1%26pageSize%3D50%26search%3D%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D196&difficulty=undefined&judgeStatus=3&tags=&title= 算法: 设maxDp[i]表示以nums[i]结尾的连续子数组的乘积的最大值,minDp[i]表示以nums[i]结尾的连续子数组乘积的最小值 初始化: maxDp[0] = nums[0] minDp[0] = nums[0] 状态转移方程: maxDp[i] = max(nums[i], nums[i] * maxDp[i-1], nums[i] * minDp[i-1]) minDp[i] = min(nums[i], nums[i] * minDp[i-1], nums[i] * maxDp[i-1]) 复杂度: 时间复杂度:O(n) 空间复杂度:O(n) """ def maxProduct(self, nums): # write code here n = len(nums) maxDp, minDp = [0] * n, [0] * n maxDp[0], minDp[0], res = nums[0], nums[0], nums[0] for i in range(1, n): maxDp[i] = max(nums[i], nums[i] * maxDp[i - 1], nums[i] * minDp[i - 1]) minDp[i] = min(nums[i], nums[i] * minDp[i - 1], nums[i] * maxDp[i - 1]) res = max(res, maxDp[i]) # print maxDp, minDp return res if __name__ == "__main__": sol = Solution() # nums = [3, 2, -1, 4] # nums = [-3, 0, -2] nums = [-3, 2, -2] res = sol.maxProduct(nums) print res
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param nums int整型vector * @return int整型 */ int maxProduct(vector<int>& nums) { // write code here int n = nums.size(); vector<int> dpmax(n + 1, INT_MIN) ,dpmin(n + 1,INT_MAX); dpmax[1] = nums[0]; dpmin[1] = nums[0]; int res= nums[0]; for(int i = 2;i <= n;i++){ if (nums[i-1] > 0){ dpmin[i] = min(dpmin[i-1] * nums[i-1],nums[i-1]); dpmax[i] = max(dpmax[i-1] * nums[i-1],nums[i-1]); } else{ dpmax[i] = max(dpmin[i-1] * nums[i-1],nums[i-1]); dpmin[i] = min(dpmax[i-1] * nums[i-1],nums[i-1]); } res = max(res,dpmax[i]); } return res; } };