【C# 每日一题9】求最大的矩形

pmars 2011-06-01 09:41:42
加精

Description

A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the heights 2, 1, 4, 5, 1, 3, 3, measured in units where 1 is the width of the rectangles:


Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.

Input

The input contains several test cases. Each test case describes a histogram and starts with an integer n, denoting the number of rectangles it is composed of. You may assume that 1 <= n <= 100000. Then follow n integers h1, ..., hn, where 0 <= hi <= 1000000000. These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is 1. A zero follows the input for the last test case.

Output

For each test case output on a single line the area of the largest rectangle in the specified histogram. Remember that this rectangle must be aligned at the common base line.

Sample Input

7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0

Sample Output

8
4000

解释一下:
输入为:7 2 1 4 5 1 3 3
的时候表示,后面有7个数字,每个数字m代表宽度为1,高度为m的矩形,之后他们都挨着,这样呢,我们需要从中间找出最大的一个矩形结构(可以跨越多个矩形,这个看图大家就理解了)!

输出找到的矩形的面积8
8来自于第三个和第四个矩形,他们两个组成了宽度为2,高度为4的矩形,面积为8

大家想想有什么好办法么?
硬算肯定是可以解决问题,但是好像效率上有点问题,也欢迎大家贴一下代码,练练手啊!!
...全文
2396 210 打赏 收藏 转发到动态 举报
写回复
用AI写文章
210 条回复
切换为时间正序
请发表友善的回复…
发表回复
iLove9ouHenry 2011-07-03
  • 打赏
  • 举报
回复
太2了!
  • 打赏
  • 举报
回复
路过,学习了。。。
myluluy001 2011-06-07
  • 打赏
  • 举报
回复
不错。。了解了
blackkettle 2011-06-07
  • 打赏
  • 举报
回复
这个题目很好玩。

大赞!
kijl000 2011-06-07
  • 打赏
  • 举报
回复
楼主要的是算法吧,,那直接:
效率高的:
1.2分查找,
楼上60楼有真相,不解释;
其实快速查找也好些,你这个数据量又不是很大,而且数据统一为u int,
2.快速查找: 
1)设置两个变量I、J,排序开始的时候:I=0,J=N-1;
  2)以第一个数组元素作为关键数据,赋值给key,即 key=A[0];
  3)从J开始向前搜索,即由后开始向前搜索(J=J-1),找到第一个小于key的值A[J],并与A[I]交换;
  4)从I开始向后搜索,即由前开始向后搜索(I=I+1),找到第一个大于key的A[I],与A[J]交换;
  5)重复第3、4、5步,直到 I=J; (3,4步是在程序中没找到时候j=j-1,i=i+1,直至找到为止。找到并交换的时候i, j指针位置不变。另外当i=j这过程一定正好是i+或j-完成的最后另循环结束)

提供思路,算法:
A[]的值转换为矩形面积即可.
qianjunbb 2011-06-06
  • 打赏
  • 举报
回复
牛人 一大片
zhoujk 2011-06-06
  • 打赏
  • 举报
回复
以你的源图为例:大致是2,1,5,6,1,4,4

//从第一个数判断在它的左侧和右侧相邻的数中,大于等于它的数的个数,
2 1 5 6 1 4 4 //源值
1 7 2 1 7 2 2 //所以与它相邻的数中,大于等于它的数的个数
//然后再遍历一次,返回这两个值的乘积
2 1 5 6 1 4 4 //源值
1 7 2 1 7 2 2 //所以与它相邻的数中,大于等于它的数的个数
2 7 10 6 7 8 8 //返回的乘积
//乘积最大值所对应的结果就是你要的定位点了。

重新对齐了一下,好看一点
zhoujk 2011-06-06
  • 打赏
  • 举报
回复
以你的源图为例:大致是2,1,5,6,1,4,4
从第一个数判断在它的左侧和右侧相邻的数中,大于等于它的数的个数,
2,1,5,6,1,4,4 //源值
1 7 2 1 7 2 2 //所以与它相邻的数中,大于等于它的数的个数
然后再遍历一次,返回这两个值的乘积
2,1,5,6,1,4,4 //源值
1 7 2 1 7 2 2 //所以与它相邻的数中,大于等于它的数的个数
2 7 10 6 7 8 8 //返回的乘积
乘积最大值所对应的结果就是你要的定位点了。
dahema0112 2011-06-06
  • 打赏
  • 举报
回复
来赚积分,顺便看看。。。
mj826kty 2011-06-05
  • 打赏
  • 举报
回复
楼上题目值得一思,强
zx568998218 2011-06-05
  • 打赏
  • 举报
回复
这还是让我上学期泪奔的C# 看着怪熟悉的
RaceBug2010 2011-06-05
  • 打赏
  • 举报
回复
时间复杂度O(n)
RaceBug2010 2011-06-05
  • 打赏
  • 举报
回复
又见ACM水题,这题考察对栈的一个应用。

#include <stdio.h>

const int maxn = 10005;

int high[maxn];
int left[maxn], right[maxn];
int stack[maxn], top;
int n, maxa;

void solve()
{
top = -1;
stack[++top] = 0;
left[0] = 0;

for (int i = 1; i <= n + 1; i++)
{
while (high[i] <= high[stack[top]])
{
right[stack[top--]] = i;
}
left[i] = stack[top] + 1;
stack[++top] = i;
}

maxa = -1;

for (int i = 1; i <= n; i++)
{
if (maxa < high[i] * (right[i] - left[i]))
maxa = high[i] * (right[i] - left[i]);
}

printf("%d\n", maxa);
}

int main()
{
while (scanf("%d", &n), n)
{
for (int i = 1; i <= n; i++)
{
scanf("%d", high + i);
}
high[0] = -2; high[n+1] = -1;

solve();
}
return 0;
}
gopojim 2011-06-05
  • 打赏
  • 举报
回复
佩服佩服,太强了,学习,学习
Windows-Linux 2011-06-05
  • 打赏
  • 举报
回复
都是牛人啊!
houyanjun 2011-06-05
  • 打赏
  • 举报
回复
【看】
KissinU 2011-06-05
  • 打赏
  • 举报
回复
动态规划
牙痴 2011-06-03
  • 打赏
  • 举报
回复
int[] nums1 = {7 , 2 , 1 , 4 , 5 , 1 , 3 , 3};
int[][] nums2 = int [nums1.length][];
nums2[0] = new int[nums1[0]];
nums2[1] = new int[nums1[1]];
...
...
nums2[nums2.length-1] = new int[nums1[nums1.length-1]];

转换成动态数组?应该叫这个吧

之后开始切。。。
nums2[0][0]...nums2[nums2.length-1][0] 计算下个数
nums2[1][1]...nums2[nums2.length-2][1] 就要麻烦点 先判断nums2[1].length 够不够2 之后计算个数
之后就同上 直到 最大长度那个结束
gangzi002 2011-06-03
  • 打赏
  • 举报
回复
数据结构没学好,目前没思路,mark下,等待……
li07057516 2011-06-03
  • 打赏
  • 举报
回复
貌似有点难度
加载更多回复(181)

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧