题目
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。如图:
1. 暴力法
首先还是用简单的思路来解答,这个题简答的可以化解为求面积最大的长方形面积,而长方形的高是两个数值之中的较小值,宽是两个数值的指针的相差,为了主程序看起来简单,我们可以设置两个比较简单的,由于要两次遍历,所以时间复杂为O(n2)代码如下:
[func maxArea(height []int) int {
s := len(height)
Finalout := 0
var low, temp int
for i:=0;i<s;i++{
for l := i+1; l <s; l++{
low = min(height[i],height[l])
temp = low * (l-i)
Finalout = max(temp,Finalout)
}
}
return Finalout
}
func min(a,b int)int{
if a<b{
return a
} else {
a = b
return a
}
}
func max(a,b int)int{
if a>b{
return a
} else{
a=b
return a
}
}
2.双指针
仔细看刚刚那个算法,其实是列举出了所有的长方形方块,然后取最大值,那么有没有可以优化器算法的能力呢? 有的。如果我们无须列举所有的方块,就可以等到最优解
其实这个盛水容器的问题,其根本在于每提高一次的高度和每减少一次的宽度之间的,带来的面积变化问题,所以,有一些高度没有发生改变,但长度变小的方块,就没有必要列举了。
举个例子,如图所示中,较小的方块很明显不会大于较大的方块,换句话说,当最低边框不变时,以此边框为高的最大长方形也就被限定了。
所以,我们只需要将两边的数字向中间推进即可,也就是如图中红,绿,橙,黑四色变换的四个框,计算量比之前的穷举就节约下了很多。
具体代码如下:
func maxArea(height []int) int {
s := len(height)
Finalout := 0
a := 0
b := s-1
var temp int
for i:=0;i < s;i++{
if height[a] < height[b]{
temp = height[a] * (b -a)
a = a +1
} else {
temp = height[b] * (b-a)
b = b-1
}
Finalout = max(Finalout,temp)
if b==a {
break
}
}
return Finalout
}
func max(a,b int)int{
if a>b{
return a
} else{
a=b
return a
}
}
以上