这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战
前言
今天来一道有意思的算法题--盛最多水的容器,看到这个题目我就想到了以前看到过的短板效应也叫做木桶原理,这个原理就是你盛水的最大量不取决于你木桶的最长板,而取决于木桶的最短板,哈哈哈,不多说了,直接上题目。
题目描述
给你n个非负整数 a1,a2,...,an,每个数代表坐标中的一个点(i, ai) 。在坐标内画n条垂直线,垂直线i的两个端点分别为(i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与x轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入:height = [1,1]
输出:1
示例 3:
输入:height = [4,3,2,1,4]
输出:16
示例 4:
输入:height = [1,2,1]
输出:2
解题思路
- 本题的主要思想就是盛水的最大容量取决于最短的那个柱子,想明白了这点问题就解决了一大半
- 本题的解法是使用双指针,一个指向数组头部,一个指向尾部,依次判断左右指针中的最小值和两个指针之间的距离的乘积,然后判断左右指针那个值更小,舍弃小的,移动指针
- 至于为什么这样操作就可以,下面我们来解释一下,假设左右指针分别指向的数是x,y,两个指针之间的距离是t,那么容量就是Math.min(x,y)*t,假设x<=y,这时,不论y如何移动新的容量都会小于移动前的容量,因为t在变小,x不变
- 这时我们就可以舍弃原来左指针指向的位置了,也就是移动左指针
- 也就是说,点比较两个指针指向的数的时候,比较小的那个数已经注定不能成为最大容量的边界了,下面上代码
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function(height) {
let left = 0
let right = height.length-1
let maxCapacity = 0//最大容量
let capacity = 0//每次移动之后的容量
while(left < right){
capacity = Math.min(height[left],height[right])*(right-left)
maxCapacity = Math.max(maxCapacity,capacity)
if(height[left]<height[right]){
left++
}else{
right--
}
}
return maxCapacity
};
LeetCode运行结果
总结
这道题目挺有意思的,不仅是道算法题,还很有哲理,努力向前,gogogo