输入一组直方图数据,其中每列的宽度为1,求所给直方图包含的最各个高度的矩形面积。比如,对于直方图[2,7,9,4,1],它所包含的各个高度矩形的面积为8,14,9,12,5
给定一个直方图及它的总宽度返回相应面积。
- 方法一:
方法一的思路是,从前完后遍历直方图,在相应的位置往前后搜索,遇到直方图高度更低的则停止,通过左右的界限来求其宽度。(方法一代码值考虑了值为0到9的情况)
#include <iostream>
using namespace std;
int main()
{
cout<<"cin a histogram and the length n:";
cout<<"such as [2,7,9,4,1],5"<<endl;
string strin;
getline(cin,strin);
int last=strin.length()-1;
int n=int(strin[last]-'0');
int his[n+1];
his[n]=0;
n=0;
int sqr[n];
for(int i=0;i<strin.length()-1;i++)
{
if(strin[i]<='9'&&strin[i]>='0')
{
his[n]=strin[i]-'0';
n++;
}
}
for(int i=0;i<n;i++)
{
int l=i,r=i;
//往左搜索
while(his[i]<=his[l] && l>=0)
{
l--;
}
//往右搜索
while(his[i]<=his[r] && r<=n)
{
r++;
}
sqr[i]=(r-l-1)*his[i];
cout<<his[i]<<' '<<sqr[i]<<endl;
}
return 1;
}
- 方法二:
方法二思路是:从左到右遍历直方图,定义一个栈,首先将直方图中第一个高度的序号入栈,往后搜索直方图,每次把栈顶元素对应的高度与当前搜索到的高度进行比较,如果当前高度高于栈顶元素,说明可以往下扩展,那么将当前高度的序号入栈。而如果当前高度低于栈顶元素对应直方图中高度,那么先求栈顶元素对应高度的矩形面积,由于当前高度低于栈顶元素高度,而栈顶元素的下一个元素对应的高度也是低于栈顶元素的(该元素是栈顶元素往左搜索的第一个高度更小的元素),因而,可以通过相应序号得到宽度。计算完该高度的矩形面积后,将栈顶元素出栈,继续比较新的栈顶元素对应高度与当前元素对应高度,仍然是栈顶元素对应高度更高,那么继续求其对应高度的矩形面积,依次循环。直到栈顶元素高度低于当前元素高度时入栈,继续往下。
此处的小技巧是,把直方图第一个元素前一位和最后一个元素后一位高度都设置为0,这样方便求第一个和最后一个序号对应的直方图。且压入栈的的方柱的索引而不是高度,因为这样方便计算横向距离。
#include <iostream>
#include <stack>
using namespace std;
int main()
{
string str;
stack<int> hisstack;
getline(cin,str);
int* his=new int;
int* sqr=new int;
int n=1;
for(int i=0;i<str.length();i++)
{
if(str[i]>='0'&& str[i]<='9')
{
his[n]=str[i]-'0';
while(str[i+1]>='0'&& str[i+1]<='9')
{
his[n]=his[n]*10+int(str[i+1]-'0');
i++;
}
n++;
}
}
int num=his[n-1];
his[n-1]=0; //把直方图之后一个高度设置为0
his[0]=0; //把直方图之前一个高度设置为0
hisstack.push(0);
int hei=0;
int wid=0;
int curindex;
for(int i=1;i<=num+1;i++)
{
if(his[i]>=his[hisstack.top()])
{
hisstack.push(i);//将相应的编号入栈,方便求其横向差值
}
else
{
while(his[i]<his[hisstack.top()])
{
hei=his[hisstack.top()];
curindex=hisstack.top();
hisstack.pop();
wid=i-1-hisstack.top();
sqr[curindex]=hei*wid;
}
hisstack.push(i);
}
}
for(int i=1;i<=num;i++)
{
cout<<his[i]<<' '<<sqr[i]<<endl;
}
return 1;
}