题目描述:
给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49
示例:
输入: [1,8,6,2,5,4,8,3,7] 输出: 49
- 暴力解法,直接遍历所有情况,得到两个竖直线最短的一条与两条竖直线之间的跨度的乘积最大的,即为结果。有时提交会超时
public class Solution {
public int MaxArea(int[] height) {
int max = 0;
int tempMax = 0;
for(int i = 0; i < height.Length; i++)
{
for(int j = i; j < height.Length; j++)
{
tempMax = Math.Min(height[i], height[j]) * (j - i);
if (max < tempMax)
max = tempMax;
}
}
return max;
}
}
2.双指针解法 由线段长度构成的数组中使用两个指针,一个放在开始,一个置于末尾。使用变量 max 来持续存储到目前为止所获得的最大面积。 之后不断找出指针所指向的两条线段中的较短的线段,并将指向较短线段的指针向较长线段那端移动一步,并更新max的值。
双指针法直接去掉了从取较长线段往较短线段移动的情况,为什么不会错过最优解呢? 因为如果取较长线段往较短线段移动,移动后的线段再长,y轴长度也是以较短线段(未移动的线段)为基准的,而两条线断之间的距离却变小了,所以其结果肯定会变小
public int MaxArea(int[] height)
{
int low = 0, high = height.Length - 1,max = 0,tempMax = 0;
while (low<high)
{
tempMax = Math.Min(height[low], height[high]) * (high - low);
if (max < tempMax)
max = tempMax;
if (height[low] > height[high])
high--;
else
low++;
}
return max;
}