【leetcode】盛最多水的容器

题目:

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (iai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (iai) 和 (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;
    }
}

猜你喜欢

转载自blog.csdn.net/kangbin825/article/details/106092554