题解 最大乘积区间问题 | 豆包MarsCode AI刷题

31 阅读3分钟

问题描述

小R手上有一个长度为 n 的数组 (n > 0),数组中的元素分别来自集合 [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]。小R想从这个数组中选取一段连续的区间,得到可能的最大乘积。

你需要帮助小R找到最大乘积的区间,并输出这个区间的起始位置 x 和结束位置 y (x ≤ y)。如果存在多个区间乘积相同的情况,优先选择 x 更小的区间;如果 x 相同,选择 y 更小的区间。

注意:数组的起始位置为 1,结束位置为 n


测试样例

样例1:

输入:n = 5, arr = [1, 2, 4, 0, 8]
输出:[1, 3]

样例2:

输入:n = 7, arr = [1, 2, 4, 8, 0, 256, 0]
输出:[6, 6]

样例3:

输入:n = 8, arr = [1, 2, 4, 8, 0, 256, 512, 0]
输出:[6, 7]

解题思路

使用队列和暴力求解的方法来寻找最大乘积的子数组

  1. 数据结构初始化

    • vector<int> res: 用来存储最终的结果,即最大乘积子数组的起始和结束索引。
    • queue<int> q: 用来存储数组中 0 的位置。0 元素作为子数组的分隔符,分割了数据。
    • queue<PII> qp: 用来存储最大乘积子数组的起始和结束位置。PII 是一个 pair<int, int> 类型,表示子数组的开始和结束位置。
  2. 循环查找 0 的位置

    • 在 for 循环中,遍历 data 数组,将所有值为 0 的索引位置推入 queue<int> q 中。
    • 这些 0 的位置将成为子数组的“分隔点”。
  3. 遍历每个分隔点

    • 设置 start = 0,表示从数组的第一个元素开始。

    • max = -1e9 是初始化的最大乘积值,用于比较各个子数组的乘积。

    • while (!q.empty()) 循环遍历所有的 0 分隔符,处理每个子数组的乘积。

      • 从 start 到当前 end = q.front() 之间的子数组被认为是一个独立的子数组(不包括当前的 0)。
      • 计算该子数组的乘积 mul
      • 如果当前子数组的乘积 mul 大于当前的最大乘积 max,则更新最大乘积,并将子数组的起始和结束位置 start 和 end 记录到 qp 队列中。
  4. 处理最后一个子数组

    • 在 while 循环结束后,判断 end < n-1,即是否存在一个在最后没有被 0 分隔的子数组。此时我们计算最后一个子数组的乘积,并更新最大乘积。
    • 如果计算的乘积大于当前的最大值 max,则将该子数组的起始和结束位置 end 和 n 推入 qp 中。
  5. 获取最大乘积子数组的起始和结束位置

    • 在所有的子数组中,只有一个最大乘积的子数组会被保留在 qp 中。为了保证我们只得到一个结果,使用 while (qp.size() > 1) 来删除队列中多余的元素。
    • 然后,取出队列中的唯一元素,即最大乘积子数组的起始和结束位置,并将其加入到 res 中。
  6. 返回结果

    • 返回的是一个包含最大乘积子数组的起始和结束位置的数组 res,位置是以 1 为起始的索引。

代码示例

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

typedef pair<int,int> PII;

vector<int> solution(int n, vector<int> data) {
    // Edit your code here
    vector<int> res;
    queue<int> q;
    queue<PII> qp;
    for(int i = 0; i < data.size(); i ++)
    {
        if(data[i] == 0) q.push(i);
    }
    int start = 0, max = -1e9, end;
    while(!q.empty())
    {
        end = q.front();
        q.pop();
        int mul = 1;
        for(int i = start; i < end; i ++)
        {
            mul *= data[i];
        }
        // cout << "mul = " << mul << endl;
        if(mul > max)
        {
            max = mul;
            qp.push({start,end});
        }
        start = end+1;
    }
    if(end < n-1)
    {
        int mul = 1;
        for(int i = end+1; i < n; i ++) mul *= data[i];
        if(mul > max)qp.push({end, n});
    }
    while(qp.size() > 1) qp.pop();
    auto t = qp.front();
    res.push_back(t.first+1),res.push_back(t.second);
    return res;
}

代码中存在的问题:

  1. 乘积溢出:数组元素的乘积可能会非常大,可能导致整数溢出。为了避免溢出,通常我们应该考虑使用 long long 类型或避免直接计算乘积。