🏑11. 盛最多水的容器
2020 5.29 00:13
YongChoir
橘子汽水
✨道阻且长,行则将至
「题目描述」:
给你 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
「题解」:
法一:双指针(两侧双指针)
观察可知,如果只有两个柱子a
、b
,那么容积v = minHeight(a, b) * width(b - a)
–>v = minH * width
. 那么只有通过长、宽两个变量变化来增加体积。那么可以通过增加宽度或者高度又或者同时增加。
-
从最左边开始遍历,稳定左边,变化右边–>增大宽度。如此嵌套循环,时间复杂度:
O(N^2)
-
初始左右柱子为左边界、右边界。那么开始移动,宽度变小,转而只能通过增加高度来找寻最大体积。而最终计算时需要的高度是二柱中矮的。所以我们只需要移动矮的柱子。
-
证明为什么只移动最矮的柱子:
假如当前两柱
nums[0]
nums[i]
,if (nums[0] < nums[i])
,那么是不用计算nums[i-1]、nums[i-2]...
。证明:
-
nums[i-1] > nums[i]
:minH = nums[0]
width
变小–>没意义 -
nums[i-1] < nums[i]
:nums[i-1] = nums[0]
:minH = nums[0]
width
变小–>没意义nums[i-1] < nums[0]
:minH < nums[0]
width
也变小–>更没意义nums[i-1] > nums[0]
:minH = nums[0]
width
变小–>没意义
-
nums[i-1] = nums[i]
:minH = nums[0]
width
变小–>没意义
所以,可得只用移动较矮的柱子即可。
-
「伪码」:
while (right < nums.length) { maxV = max (maxV, (right - left) * min(left, right)); if (left <= right) { left++; }else{ right--; } }
「Code」:
class Solution { /** * 时间复杂度:O(N) * 空间复杂度:O(1) */ public int maxArea(int[] height) { int left = 0; int right = height.length - 1; int maxV = (right - left) * Math.min(height[left], height[right]); while (left < right) { maxV = Math.max(maxV, (right - left) * Math.min(height[left], height[right])); if (height[left] <= height[right]) { left++; }else{ right--; } } return maxV; } }
Good Evening! 😴 😴 😴
-