题目链接 https://leetcode-cn.com/problems/container-with-most-water
给你 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
提示:
n = height.length
2 <= n <= 3 * 104
0 <= height[i] <= 3 * 104
解析:
刚看到这个问题时,最直接的想法就是将所有的组合都穷举出来,记录组合最大的值,这是最直接的方法,但是时间复杂度高,并且在LeetCode上执行时,因为测试用例给的数据非常大,导致超时,知道肯定有其他巧妙的方法,但是不知是什么,后来看了官方的解释说明,恍然大悟。其实所谓的一些巧妙的算法,都是在运算过程中,将一些没有必要计算的东西给舍弃或者使用已经计算好的东西来节省时间。
这个题是蛮有意思的,其实说白了,就是要找 距离越远越好,高度越高越好的两个数,既然越远越好,那就从最外侧的两个开始计算,计算的值应该是两个数的坐标的差乘上两个中小的数,那么下一步,我们就要找比这个大的,比这个值小的,我们没有必要找了,那,就是要移动其中一端的坐标,移动哪个呢?这个是关键,如果移动值比较大的那一端的坐标,得到的下一个结果,肯定比现在的结果小,因为,高度是由短板决定的,而一旦移动一端,那么宽度肯定会变小,那就是说,移动数值大的一端是没有必要的(这里就是算法节省的时间),那就移动数值小的一端,进行计算,和现在的最大结果进行比较并记录下大者,依次这样进行,直到两端走到一起。
说的书面一点,这个算法叫双指针具体的讲解,上面的链接到leetcode中有官方的视频讲解。自己实现代码如下
java:
class Solution {
public int maxArea(int[] height) {
if(height.length<2) return 0;
int leftIndex = 0,rightIndex = height.length - 1;
int maxArea = 0;
while(leftIndex < rightIndex){
maxArea = Math.max(maxArea, Math.min(height[leftIndex],height[rightIndex]) * (rightIndex - leftIndex));
if(height[leftIndex] < height[rightIndex]){
leftIndex++;
} else {
rightIndex--;
}
}
return maxArea;
}
}
python:
class Solution:
def maxArea(self, height: List[int]) -> int:
if len(height) <2:
return 0
leftIndex, rightIndex = 0, len(height)-1
maxArea = 0
while leftIndex < rightIndex:
maxArea = max(maxArea, min(height[leftIndex], height[rightIndex]) * (rightIndex - leftIndex))
if height[leftIndex] < height[rightIndex]:
leftIndex = leftIndex + 1
else:
rightIndex = rightIndex - 1
return maxArea
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/container-with-most-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。