0
点赞
收藏
分享

微信扫一扫

[动态规划]DP8 乘积为正数的最长连续子数组-中等

​​DP8 乘积为正数的最长连续子数组-中等​​

描述

输入一个长度为 n 的整型数组 nums,数组中的一个或连续多个整数组成一个子数组。求所有子数组的乘积的最大值。

1.子数组是连续的,且最小长度为 1 ,最大长度为 n

2.长度为 1 的子数组,乘积视为其本身,比如 [4] 的乘积为 4

3.该题的数据保证最大的乘积不会超过 int 的范围,即不超过[动态规划]DP8 乘积为正数的最长连续子数组-中等_最大乘积

数据范围:

[动态规划]DP8 乘积为正数的最长连续子数组-中等_最大乘积_02

[动态规划]DP8 乘积为正数的最长连续子数组-中等_最大乘积_03

输入描述:

第一行输入一个正整数 n ,表示数组的长度

第二行输入 n 个整数,表示数组中的值。

输出描述:

输出子数组的乘积的最大值

示例1

输入:

4
3 2 -2 4

输出:

6

说明:

子数组[3,2]的乘积为6,[3,2,-1,4]的乘积为-24,[4]的乘积为4,故返回6

示例2

输入:

3
-3 0 -2

输出:

0

说明:

因为0在中间,所有包含0的子数组的乘积都为0,另外的数都是负数,所以最大乘积的子数组为[0],返回为0,因为子数组要求是连续的,所以[-3,-2]不是[-3,0,-2]的子数组,所以不能为6,

示例3

输入:

3
-3 2 -2

输出:

12


题解

动态规划解法

这个是​​DP7 连续子数组的最大乘积-中等​​变种,求最大乘积时我们使用dp数组存放的是乘积之和,求长度的时候,我们只需要用dp数组存放对应的长度即可。

步骤如下:

  1. 使用positive_dp[i]和negative_dp[i]分别表示以索引i结尾的时候乘积为正数和乘积为负数的最大长度
  2. positive_dp[0]初始化:如果v[0]大于0则取1,否则取0
  3. negative_dp[0]初始化:如果v[0]小于0则该值取1,否则取0
  4. 递推关系:
  1. 如果v[i] == 0,则positive_dp[i]=negative_dp[i]=0,因为0乘以任何数都为0,因此乘积长度为0
  2. 如果v[i]大于0,则p[i] = p[i-1]+1,因为正数只能和正数相乘得到正数,因此取上一个的最长正数长度+1;此时如果n[i-1]大于0表示前面的数相乘是负数,取n[i]=n[i-1]+1,否则n[i]=0
  3. 如果v[i]小于0,则n[i]=p[i-1]+1,因为要让乘积为负数最长,只能尽量长的取i-1为正数的情况;此时p[i]应该让负数的长度尽可能场,如果n[i-1]大于0则p[i]=n[i-1]+1,否则由于当前是负数,而i-1之前不是负数,因此乘积还是负数或者0,因此p[i]=0

步骤可能有点啰嗦,但实际上代码逻辑很简单~~

代码如下:

#include <bits/stdc++.h>

int64_t solve(std::vector<int64_t> &v)
{
if (v.size() == 1)
{
return v[0] > 0 ? 1 : 0;
}

// 分别表示以索引i为结尾时,最长乘积为正数的长度、最长乘积为负数的长度
std::vector<int64_t> positive_dp(v.size(), 0);
std::vector<int64_t> negative_dp(v.size(), 0);
int64_t ans = 0;
positive_dp[0] = v[0] > 0 ? 1 : 0;
negative_dp[0] = v[0] < 0 ? 1 : 0;
for (int i = 1; i < v.size(); ++i)
{
if (v[i] == 0) // 以i结尾的乘积为0,则正负dp的长度也是0
{
continue;
}

if (v[i] > 0)
{
positive_dp[i] = positive_dp[i - 1] + 1;
negative_dp[i] = negative_dp[i - 1] > 0 ? (negative_dp[i - 1] + 1) : 0;
}
else
{
positive_dp[i] = negative_dp[i - 1] > 0 ? (negative_dp[i - 1] + 1) : 0;
negative_dp[i] = positive_dp[i - 1] + 1;
}
ans = std::max(ans, positive_dp[i]);
}

return ans;
}
int main()
{
int n, x;
std::cin >> n;
std::vector<int64_t> v;
while (n-- > 0)
{
std::cin >> x;
v.push_back(x);
}

std::cout << solve(v) << std::endl;
return 0;
}

举报

相关推荐

DP7 连续子数组的最大乘积

0 条评论