前言:这道题其实挺有意思的,前段时间在刷视频的时候看都了很多博主都在讲解这道题,最近在写一些算法的东西,我就顺势刷到了这道题。在这里写一写我自己的对这道题的理解。
题目详见:https://leetcode.cn/problems/container-with-most-water/description/
思路:这道题第一眼的直觉直接暴力,必定可以对一部分数据的。
直接秒了,但是......不出意外。。。。
超时,其实想想也是肯定的,不然这题不是都傻子吗。
正确思路:因为棒子有长短,所以在两根棒中间可以盛的水一定是由短的那一根来决定的。所以这个时候我们应该要有一个直觉就是我们在看这一个空间可以盛多少水的时候一定是两个木板一起看的。
这时候其实有一个双指针的算法是很合适去实现的。以最左边索引为0的记为左指针和索引最大的那个为右指针。然后慢慢往里缩例举每种情况可以盛下的水就可以,比较哪个是最多的就可以。
现在要解决的问题就是如何去移动这两个指针,这是最关键的,如何去移动才能避免漏过最大盛水可能情况呢。
1.首先最容易想到的是将左指针和右指针同时向中间移动。但是明显,这是有缺陷的。两边一起往里缩,这样就只是计算了对称的两个木板所能盛的水,万一这个是索引0和索引3形成的是最大盛水量(3不是最大的索引),很容易就淘汰了这种做法。
2.再者,肯定不能盲目的去随意缩进一边指针了,那就要比个大小。假设是以大的哪个缩进一个。但是如何算两个木棒之间的空间的?是以小的那个来决定的,那如果你把大的那个指针缩进去之后那所盛水的体积必定是变小的,你想,长减少了1,然后又把大的那个木板动了,但是小的那个没有动,但是盛水的时候判断的时候是以小的那根判断的,所以你动了大的那根以后,你所可以盛水的体积一定不会比之前的情况大。
综上所述,运用双指针,然后比较左右指针所指向的木棒大小,小的那一根往里动一根。就可以了。具体的动画题解各大平台都有,leetcode官网也给出了详细的题解,若想了解,可以前往那里学习。
附上代码:
class Solution {
public int maxArea(int[] height) {
int max = -100;
int left = 0;
int right = height.length-1;
while (left != right) {
int sum = (right - left) * (height[left] > height[right] ? height[right] : height[left]);
if (sum > max) {
max = sum;
}
if (height[left] > height[right]) {
right -= 1;
} else {
left += 1;
}
if (right==left){
break;
}
}
return max;
}
}