<Leetcode> Container With Most Water(逻辑思维)

1.题目

这里写图片描述

2. 分析

  暴力解法,就不提了,笔者一开始写的也是暴解。在看了官网推荐的Two Pointer Approach比较有感触,现在记录下。

Initially we consider the area constituting the exterior most lines. Now, to maximize the area, we need to consider the area between the lines of larger lengths. If we try to move the pointer at the longer line inwards, we won’t gain any increase in area, since it is limited by the shorter line. But moving the shorter line’s pointer could turn out to be beneficial, as per the same argument, despite the reduction in the width. This is done since a relatively longer line obtained by moving the shorter line’s pointer might overcome the reduction in area caused by the width reduction.

  上面的论述并没有严格的证明,一般思考到这里,可以当结论记住。但是本算法的营养可能就没有那么充分了。笔者刚开始不太能接受该算法,因为觉得可能会漏情况。
  现在从逻辑上顺推理解:

  • 我们都能想到 O ( n 2 ) 的解法,也就是暴力解法。
  • 我们都想优化该暴力解法,将二次优化到线性。
  • 优化的本质就是减少了计算case的次数,也就是说根据一些特有的性质来减少循环遍历case的个数
  • 思考水桶问题的一些特性:
    • 短板效应:也就是水的容积取决于最短的一边的长度
  • 遍历方式的选择:

    • 套嵌for循环,可以保障遍历所有的case
    • 优化套嵌方式,使用两个指针代表水桶两边,如果没有考虑性质特点,该方式同样是 O ( n 2 ) 。(意味着leftright会交叉)
      for(left=0;left<n;left++)
        for(right=n-1;right>=0;right--)
      
  • 现在优化上面的for套嵌:
    • 如果left小于right,我们只需要右移leftleft+1),而不必让该left再遍历right其他情况。因为right和left此时已经是最大容积!多想想,这点很关键。同理,left大于right,左移right
    • 思考边界条件:leftright交叉为止。

3. 实现

  笔者上面的分析,是站在一个coder如何在20分钟内,解决一个新问题的角度。我相信第一个想出来该算法的人,一定经过类似的思考过程。下面就是根据笔者的思考写出来的代码,和官网实现不太相同:

int maxArea(int* height, int heightSize) {
    int left,right,max=0,tmp=0;
    for(left=0,right=heightSize-1;left<right;){
        if(height[left]<=height[right]){
            tmp=height[left]*(right-left);
            left++;
        }
        else{
            tmp=height[right]*(right-left);
            right--;
        }
        if( tmp > max)
            max=tmp;
    }
    return max;
}

  再看看AC time:
这里写图片描述

4. 总结

  算法更加重要的是思考过程,解决一个题能让你有解决其他10个题的思路。从逻辑思维出发,思考该问题的解决方式(而非知道结果反推过程)。力求能培养以后解决其他新问题的能力。

猜你喜欢

转载自blog.csdn.net/lovestackover/article/details/80397886