题目描述
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
测试用例的答案是一个 32-位 整数。
子数组 是数组的连续子序列。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximum-product-subarray
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题
定义一个二维数组dp[n][n]
, 每一个元素dp[i][j]
记录从i位置到j位置的乘积,利用变量max
实现每次更新dp之后记录当前乘积最大值
class Solution {
public int maxProduct(int[] nums) {
int max = nums[0], n = nums.length;
int[][] dp = new int[n][n];
dp[0][0] = nums[0];
for(int i = 0; i< n;i++){
for(int j = i; j< n;j++){
if(i == j){
dp[i][j] = nums[i];
}else{
dp[i][j] = dp[i][j-1] * nums[j];
}
max = Math.max(max, dp[i][j]);
}
}
return max;
}
}
好, 去提交
错了!!!!提示超出内存限制
接下来优化代码,发现该代码优化后的时间复杂度也会是O(n^2)
需要换个思路:
同时记录最大值和最小值,这样的话如果当前元素是正数那么就乘最大值,如果当前元素是负数就乘最小值
class Solution {
public int maxProduct(int[] nums) {
int n = nums.length;
int[] maxF = new int[n];
int[] minF = new int[n];
System.arraycopy(nums, 0, maxF, 0, n);
System.arraycopy(nums, 0, minF, 0, n);
for (int i = 1; i < n; ++i) {
maxF[i] = Math.max(maxF[i - 1] * nums[i], Math.max(nums[i], minF[i - 1] * nums[i]));
minF[i] = Math.min(minF[i - 1] * nums[i], Math.min(nums[i], maxF[i - 1] * nums[i]));
}
int ans = maxF[0];
for (int i = 1; i < n; ++i) {
ans = Math.max(ans, maxF[i]);
}
return ans;
}
}
附:System.arraycopy()有什么作用
System.arraycopy()
是Java中的一个方法,它可以用来将一个数组中的一部分元素复制到另一个数组中。 它的目的是在效率方面提高数组操作。
该方法有多个重载,基本语法为:
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
其中各参数含义如下:
src
: 源数组srcPos
: 源数组中被复制的起始位置dest
: 目标数组destPos
: 复制到目标数组中的起始位置length
: 要复制的元素个数
使用 System.arraycopy()
方法可以避免手动循环,并且代码可读性更好,同时也能提升程序效率。