求数组中区间中最小数*区间所有数和的最大值

该博客详细介绍了如何解答今日头条的一道编程题,即找到数组中区间最小数乘以区间所有数和的最大值。作者提供了两种解法,一是暴力解法,时间复杂度较高;二是使用单调栈优化,通过遍历数组并维护单调栈,实时计算以当前元素为最小值的区间和的最大值,从而提高效率。在解题过程中,作者给出了具体的示例和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今日头条编程题第二道

这里写图片描述

解答

解法一:暴力解法

穷举所有数组中所有子数组,并计算所有子数组中最小值*子数组所有数的和,求出其中的最大值即可,代码如下:

int enum_method(vector<int> &num) {
    int n = num.size();
    int maxSum = INT_MIN;
    vector<int> tmp;
    for (int i = 0; i<n; ++i) {
        for (int j = i; j<n; ++j) {
            tmp.clear();
            for (int k = i; k <= j; ++k) {
                tmp.push_back(num[k]);
            }
            sort(tmp.begin(), tmp.end());
            int curSum = tmp[0] * vecSum(tmp, 0, tmp.size() - 1);
            maxSum = max(curSum, maxSum);
        }
    }
    return maxSum;
}

时间复杂度为O(N*N*N)

解法二:单调栈解法

基本思想:
1. 以数组中每一个值为最小值,假设这个最小值为num[k], 分别找到以该值num[k]为最小值,数组最左边的小于该值的下标i,和数组最右边的小于该值的下标j, 则区间num[i+1,j-1]为以num[k]为最小值所能达到的最大区间,则此区间能达到的最大值为num[k]*Sum(i+1,j-1),其中Sum函数为数组中区间[i+1,j+1]的所有数的和
2. 按照步骤1(可利用单调栈实现)结算数组中每一个值,维护一个最大值maxSum, 当遍历数组的最后一个数,所得maxSum即为所求。

举例说明步骤1单调栈的实现:

如现在有一个数组vector<int> num=[6,2,5,5,5,4,7], 接着我们创建一个栈stack<int> s,我们将数组的数压栈入栈的规则如下:

  1. 如果s为空,或者当前遍历元素num[i]的值大于等于栈顶元素,那么我们直接将num[i]的下标i压入栈中。
  2. 如果s不为空,且当前遍历元素num[i]的值小于等于栈顶元素,那么我们就依次从栈中弹出元素,直到num[i]的值大于栈顶元素。并在弹出的过程中结算弹出中每一个数所构成的区间的区间中最小数*区间所有数和的最大值。
  3. 如果数组中的元素已经全部遍历压栈,如果此时栈不为空,我们就重复步骤2,将栈中的元素全部结算。

如现在我们开始遍历数组[6,2,5,5,5,4,7],

  1. 遍历到6时,因为此时栈为空,我们直接将6的下标0压入栈中。此时栈中元素为{0}
  2. 遍历到2时,此时栈不为空,且num[i]=2<6(栈顶元素),根据规则2,则将6的下标0出栈保存到top,并结算以6为最小值的最大区间的最大值。即我们知道6最左边小于6的元素的下标是不存在,那么我
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值