leetcode_11:Container With Most Water

初始思路

这个题我一看到的时候感觉不会很难,然后看了一会有了解题思路:肯定是两个指针分别从首部和尾部往中间靠拢,然后找出其中的最大值,关键就是怎么移动这两个指针,或者说这两个指针是按照什么规则来改变。然后又拿了给的例子,发现既然求最大,那两边的指针谁的下一步最大,就应该先移动谁,即

if ((height[high-1] - height[high]) >= (height[low+1] - height[low])) {
	high--;			//若右边增加的比较多(减少的比较少),则右边指针移动
} else {
	low++;			//否则左边指针移动
}

但是发现不对劲啊,虽然给的例子结果是对的,但测试用例是错的,于是我陷入了沉思,开始回忆自己刚才在干什么,要干什么,从哪里来,到哪里去…最后我发现了,那个思路就是错的,即使有一边增长的比较快,但如果另一边一直都是1,那再快总的面积也没有增加,相反因为指针不断移动,会导致面积逐渐变小,所以这个关键点在于两个指针所指的值的最小值,也就是木桶效应。于是重新审视,有了以下思路。

正确思路

这个过程中,面积一直是由两个指针所指的值中最小的那个决定的,假如现在两个指针在各自的初始位置,此时的最大面积就是初始围成的面积。然后左边的值较小,则移动左边的指针向前,这时候左边指针指向的值会有三种变化情况:

  1. 值变的更小了。那么此时面积会更小,所以最大值不变
  2. 值不变。那么此时面积会减1,因为两个指针的距离减了1,所以最大值不变。
  3. 值变大了。当然这种情况可能导致面积变大或变小,而且有可能会更新最大值。

总之,这时候就是应该移动左边的值,才有可能使最大值更新。相反,如果左边值较小时移动右边指针,则不管右边的值变大还是变小,面积都会减小,因为面积总是(两者原始间隔-1)*左边值。所以正确的移动策略是更新较小值那边的指针。代码如下:

class Solution {
    public int maxArea(int[] height) {
        int result = 0;
        int i = 0, j = height.length - 1;
        while (i < j) {
            int cur = (j-i) * Integer.min(height[i], height[j]);
            result = cur > result ? cur : result;
            if (height[i] >= height[j]) {	//左边高则移动右边指针
                --j;
            } else {		//右边高则移动左边指针
                ++i;
            }
        }
        return result;
    }
}

当然还有一种暴力的方法,就是求出每一种可能,然后找最大值,代码如下:

class Solution {
    public int maxArea(int[] height) {
        int result = 0;
        for (int i = 0; i < height.length; ++i) {
            for (int j = i+1; j < height.length; ++j) {
                int cur = (j-i) * Integer.min(height[i], height[j]);
                if (result < cur) {
                    result = cur;
                }
            }
        }
        return result;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值