LeetCode百题【乘积最大子数组I,II】
题目描述
解法
动态规划
dp[i]为存储第i个元素结尾的乘积最大的子数值的乘积
很容易得到动态方程:dp[i]=dp[i-1]*nums[i]与num[i]当前值进行比较
问题是,当dp[i-1]与num[i]异号时,该动态方程就失效了
考虑当前位置如果是一个负数的话,那么我们希望以它前一个位置结尾的某个段的积也是个负数,这样就可以负负得正,并且我们希望这个积尽可能「负得更多」,即尽可能小。
如果当前位置是一个正数的话,我们更希望以它前一个位置结尾的某个段的积也是个正数,并且希望它尽可能地大。
状态转移方程为
1 |
|
1 |
|
- 时间复杂度:O(n)
来源:力扣(LeetCode)
链接:152. 乘积最大子数组 - 力扣(LeetCode) (leetcode-cn.com)
题目描述
解法
动态规划
最大乘积数组相类似,也需要维护一个最大正数和一个最大负数的长度
dp[]为数的最长子数组长度
若nums[i]>0 (dp[i]的符号不会因此改变)
正数组[i]在正数组[i-1]基础上+1 (因为正数组[i-1]是否为0不影响,因为当前的num>0)
若负数组[i-1]>0则在原来的dp[i-1]上+1,若负数组i-1为0则要置0
若nums[i]<0 (dp[i]的符号会因此改变)
- 正数组[i]在负数组[i-1]基础上+1 ,若负数组为0,则正数组置0(因为此时受到负数组[i-1]的影响,因为当前的num<0)
- 负数组[i]在正数组[i-1]基础上+1 (因为正数组[i-1]是否为0不影响,因为当前的num<0)
若num[i]=0,两个数组都要重新计数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39class Solution {
public int getMaxLen(int[] nums) {
int dpPositive[]=new int[nums.length];
int dpNegative[]=new int[nums.length];
dpPositive[0]=0;
dpNegative[0]=0;
if(nums[0]>0)
dpPositive[0]=1;
else if (nums[0]<0)
dpNegative[0]=1;
for (int i = 1; i < nums.length; i++) {
if(nums[i]>0){
dpPositive[i]=dpPositive[i-1]+1;
if(dpNegative[i-1]>0)
dpNegative[i]=dpNegative[i-1]+1;
else
dpNegative[i]=0;
}
else if (nums[i]<0){
if(dpNegative[i-1]>0)
dpPositive[i]=dpNegative[i-1]+1;
else
dpPositive[i]=0;
dpNegative[i]=dpPositive[i-1]+1;
}else{
dpNegative[i]=0;
dpPositive[i]=0;
}
}
int max=dpPositive[0];
for (int i = 1; i < dpPositive.length; i++) {
if(dpPositive[i]>max){
max=dpPositive[i];
}
}
return max;
}
}- 时间复杂度 O(n);
来源:力扣(LeetCode)
链接:1567. 乘积为正数的最长子数组长度 - 力扣(LeetCode) (leetcode-cn.com)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 漫漫长夜!