微信公众号:程序员Alex
关注可了解更多的编程知识。问题或建议,请公众号留言;
如果你觉得文章对你有帮助,欢迎关注分享
盛最多水的容器
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/container-with-most-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
说明
你不能倾斜容器,且 n 的值至少为 2。
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解题思路
通过分析题目,结合图表可以发现,此题其实就是求数组元素组成的长方形的最大面积。数组中的元素代表长方形的长,两个元素之间的距离(坐标差)就是长方形的宽。取数组中的第m和第n个数(满足m < n),结合木桶效应,长方形的长取决于相对短的。得出以下公式:
长
=
M
i
n
(
h
e
i
g
h
t
[
m
]
,
h
e
i
g
h
t
[
n
]
)
长 = Min(height[m] , height[n])
长=Min(height[m],height[n])
宽
=
n
−
m
宽 = n - m
宽=n−m
容
量
=
M
i
n
(
h
e
i
g
h
t
[
m
]
,
h
e
i
g
h
t
[
n
]
)
∗
(
n
−
m
)
容量 = Min(height[m] , height[n])* (n-m)
容量=Min(height[m],height[n])∗(n−m)
求最大容量则需要计算出所有可能的容量,取其中最大值。
方法1 采用双指针法
-
确定左右指针
左指针 left :数组的第0个元素
右指针 right :数组的最后一个元素
-
计算容量(长方形面积)
m a x A r e a = M i n ( h e i g h t [ l e f t ] , h e i g h t [ r i g h t ] ) ∗ ( r i g h t − l e f t ) maxArea = Min(height[left] , height[right])* (right-left) maxArea=Min(height[left],height[right])∗(right−left)
-
挪动指针
条件:将指针指向元素较小的指针向另一个指针靠近一个单位
-
计算指针移动后容量,并与之前的最大容量做比较,更新最大容量值。
-
重复步骤3和4,直至指针相遇。
核心代码实现
完整代码:https://github.com/tinet-shenjg/leetCode4J
/**
* 计算最大容量
*
* @param height n 个非负整数集合
*
* @return 最大容量
*/
public static int maxArea(int[] height) {
// 定义最大容量
int maxArea = 0;
// 采用双指针来计算最大容量
int left = 0;
int right = height.length - 1;
// 指针第一次相遇为终结点
while (left < right) {
// 计算当前的最大容量
maxArea = Math.max(maxArea, Math.min(height[left], height[right]) * (right - left));
// 移动指针,相对短的木板向另一侧一定
if (height[left] > height[right]) {
right--;
} else {
left++;
}
}
return maxArea;
}
测试用例
public static void main(String[] args) {
int[] height = {1, 8, 6, 2, 5, 4, 8, 3, 7};
System.out.println(maxArea(height));
System.out.println(maxArea2(height));
}
复杂度分析
时间复杂度O(n)
空间复杂度O(1)
方法2 暴力穷举
不推荐此方法,两层循环遍历数组即可。
代码实现
public static int maxArea2(int[] height) {
int maxarea = 0;
for (int m = 0; m < height.length; m++){
for (int n = m + 1; n < height.length; n++){
maxarea = Math.max(maxarea, Math.min(height[m], height[n]) * (n - m));
}
}
return maxarea;
}
复杂度分析
时间复杂度O( n 2 n^2 n2)
空间复杂度O(1)