问题描述
小S最近在分析一个数组 ℎ1,ℎ2,...,ℎ𝑁h1,h2,...,hN,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 𝑘k 个相邻元素时,如何计算它们所能形成的最大矩形面积。
对于 𝑘k 个相邻的元素,我们定义其矩形的最大面积为:
𝑅(𝑘)=𝑘×𝑚𝑖𝑛(ℎ[𝑖],ℎ[𝑖+1],...,ℎ[𝑖+𝑘−1])R(k)=k×min(h[i],h[i+1],...,h[i+k−1])
即,𝑅(𝑘)R(k) 的值为这 𝑘k 个相邻元素中的最小值乘以 𝑘k。现在,小S希望你能帮他找出对于任意 𝑘k,𝑅(𝑘)R(k) 的最大值。
测试样例
样例1:
输入:
n = 5, array = [1, 2, 3, 4, 5]
输出:9
样例2:
输入:
n = 6, array = [5, 4, 3, 2, 1, 6]
输出:9
样例3:
输入:
n = 4, array = [4, 4, 4, 4]
输出:16
题目分析
本题是一道典型的单调栈问题,我们需要求出其中k个连续的子序列其中的最小值乘以此时k的值的最大值,此时我们可以考虑去应用单调栈。单调栈是栈的一种衍生应用,常用于解决连续递增子序列,以及对第i个序列元素求出大于其本身的下一个序列元素的下标位置。
具体解题思路
- 从0到n-1依次遍历序列元素,对于其中的元素内容,第0个元素直接入栈,其后的元素需要与此时的栈顶元素相作比较,若大于此时的栈顶元素,则直接入栈,否则,将栈顶元素出栈,直到栈为空或者栈顶元素小于此时的下标元素a[i]
- 此时可以确保栈里的元素为单调递增或相等,那么对于每次出栈环节,我们需要统计一下此时t = s.top(),然后出栈,统计从最新的s.top()到i-1的宽度,然后统计a[t]*(i - s.top() - 1)并更新最大值
- 最后输入ans即为所求
下面是我写的代码(C++)
#include<bits/stdc++.h>
using namespace std;
int solution(int n, std::vector<int> a) {
stack<int>s;
a.insert(a.begin() , 0);
a.push_back(0);
int len = a.size();
int maxarea = a[0];
s.push(0);
for(int i = 1; i < len;i++)
{
while(a[i] < a[s.top()])
{
int t = s.top();
s.pop();
maxarea = max(maxarea , a[t]*(i - s.top() - 1));
}
s.push(i);
}
return maxarea;
}
int main() {
// Add your test cases here
vector<int>a;
int n;
cin >> n;
int i;
for(i = 0; i < n;i++)
{
int t;
cin >> t;
a.push_back(t);
}
cout << solution(n,a);
return 0;
}
关键步骤讲解
- 对于动态数组a,需要先在数组开头及结尾各加上一个0,方便处理数据。
- 随后就是应用单调栈的写法,完成对最大值ans的更新求值。
- 最后即输出所得。
写在最后
这道题有助于帮助大家更好的认识和运用单调栈的相关知识,帮助大家更熟练的运用单调栈去解决实际问题。