Skip to content

Latest commit

 

History

History

1840.Maximum-Building-Height

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

1840.Maximum-Building-Height

对于没有限制的地段,我们可以任意发挥,暂时不考虑。我们只考虑有限制的这些楼,我们记这些楼的位置是pos[i](即restrictions[i][0]),高度限制是limit[i](即restrictions[i][1]),我们打算盖的高度是h[i]。

我们先假想每个楼都可以盖到最高,即h[i] = limit[i]。但这是不可能的,因为还有一个约束是实际相邻两幢楼之间差距不超过1. 因为我们说过暂不考虑没有高度限制的地段,所以这个约束本质是说,任意两幢有限高的楼之间,需要满足h[i]与h[i-1]的高度差不能超过pos[i]-pos[i-1]. 注意这是必要条件,不满足的话就无法保证“实际相邻两幢楼之间差距不超过1”。

至此,我们可以借鉴LC135.Candy的思路,因为我们已知h[1]=0,那么可以先从左往右扫一遍,根据h[i-1]来制约h[i]。即h[i] = min(limit[i], h[i-1]+pos[i]-pos[i-1]). 扫一遍之后保证了h数组里,每个楼都不会比它左边“不合理地高”。也就是说,如果h[i]比h[i-1]高,也不会违反高度差的约束。

接下来我们再从右往左扫一遍,根据h[i+1]来进一步限制h[i],即h[i] = min(h[i], h[i+1]+pos[i+1]-pos[i]). 扫一遍之后保证了h数组里,每个楼都不会比它右边“不合理地高”。也就是说,如果h[i]比h[i+1]高,也不会违反高度差的约束。

这两遍操作的本质是什么呢?本质是:对于h数组中任意相邻的两幢楼,如果存在高度差,那么这个高度差是合理的!(也就是h[i]与h[i-1]的高度差不能超过pos[i]-pos[i-1])。也就是说,此时的h数组是符合条件的安排。

我们再看一下,这两遍pass本身都是必要条件,即每个h[i]都不允许更高。但是最终我们神奇地发现,这个结果又是充分的。这说明我们得到了h[i]的最优解(即允许的最大值)。

现在我们已经优化了所有的h[i],那么如何处理每个h[i]之间的那些没有高度限制的楼呢?很显然,我们会将h[i]往右不断增1,同时h[i+1]往左不断增1,查看这个peak会有多高。注意,我们保证了h[i]和h[i+1]的高度差是不超过pos[i+1]-pos[i]的,所以这个peak是一定存在的。我们可以这么计算,令peak距离h[i]是x,距离h[i+1]是y,则

h[i]+x = h[i+1]+y
pos[i]+x = pos[i+1]-y

可以知道这个peak的高度等于 h[i]+x = h[i+1]+y = ((h[i]-h[i+1]) - (pos[i]-pos[i+1))/2

我们把每个间隔的peak都算出来取最大值。特别注意,h数组的最后一个楼往后,还有楼可以继续不停高度增一,记得补上h[m]+n-pos[m].