【leetcode】盛最多水的容器
题目:
给你 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
思路:
(1)计算面积最大值的初值,该初值以数组中的第一个元素和最后一个元素构成两边。
(2)设置首尾两个指针,首指针i指向数组中的第一个元素,尾指针j指向数组中的最后一个元素。
(3)当首指针i小于尾指针j时,一直循环计算其面积。若计算所得的当前面积大于(1)步骤中所计算得的面积最大值,则更新最大值。每一次循环都舍弃索引i和索引j中较短的那一条边。
为什么每一次循环舍弃索引i和索引j中较短的那一条边,我们最终得到的结果就会是最大的面积值呢?
反证法:
假设我们现在遍历到了height数组中第i和第j个元素,且height[i] < height[j],如果我们的面积最大值中取了第i个元素,那么构成我们的面积最大值的两个元素一定是i和j,因为j继续减小的话长方形的宽肯定一直在减小,而其高最多只能是height[i],不可能比height[i]更大,因此我们在继续遍历的过程中,继续保持i不变而减小j是没有意义的。我们可以直接舍弃i,从i + 1开始去继续遍历。
由于整个过程只遍历了一次数组,因此时间复杂度为O(n),其中n为数组height的长度。而使用空间就是几个变量,故空间复杂度是O(1)
java代码:
public class Solution {
public int maxArea(int[] height) {
int n = height.length;
int i = 0;
int j = n - 1;
int area = (n - 1) * Math.min(height[i], height[j]);
while(i < j) {
area = Math.max(area, (j - i) * Math.min(height[i], height[j]));
if(height[i] < height[j]) {
i++;
}else {
j--;
}
}
return area;
}
}