leetcode经典问题——11.盛水最多的容器

11.盛水最多的容器

题目描述:

 

 1、暴力双重循环

思路:首先拿到这道题我们需要找盛水最多的容器,看图很明显发现,这个盛水最多的容器无视了中间垂线的高度,只需要盛水,可以只看做我们只需要关注两条线,l 和 r,找到这两条线就可以计算出此时盛水的数量,Math.min(height(l),height(r))*(r - l);

我们只需要遍历数组height,外循环定义 l 这条线的位置,内循环定义 r 这条线的位置,再分别算出各个位置的盛水数量就可。

来看看代码:

 public int maxArea(int[] height) {
        int maxArea = 0,temp = 0;
        int min;
        for (int l = 0; l < height.length-1; l++) {
   //当上一条线大于当前线,则证明可以跳过本次循环
            if ( temp >= height[l]) continue;   
            temp = height[l];
            for (int r = l+1; r < height.length; r++) {
                min = Math.min(temp,height[r]);
                maxArea = Math.max(maxArea,min*(r-l));
            }
        }
        return maxArea;
    }

时间复杂度:由于是双重循环,所以为O(n^2)

空间复杂度:O(1)

2、引入双指针

思路:第一种方法我们是固定 l 的位置,移动 r 的位置,来得到每一个位置的盛水数量再比较,我们不难看出这种方法十分耗费时间,双重循环,也会算出很多重复值,所以我们会想能不能优化一下?

当然可以,我们可以引入两个指针变量,l 和 r,因为我们求盛水数量,关键点在于两条边界线,找出两者最小值Math.min(height(l),height(r))*(r - l),所以我们可以引入一个判断条件,当height(l)<height(r)时,证明当前位置盛水数量=height(l)*(r-l),再移动l指针,l++;反之当height(r)<height(l)时,证明当前位置盛水数量=height(r)*(r-l),再移动r指针,r--即可;这样我们就只需要遍历一轮,当l = r 证明,循环可以结束了。

看看代码:

public int maxArea(int[] height) {
      int l = 0,maxArea = 0;
        int r = height.length -1;
        while (l < r){
            maxArea = height[l] < height[r]
                    ? Math.max(maxArea,(r-l)*height[l++])
                    : Math.max(maxArea,(r-l)*height[r--]);
        }
        return maxArea;
    }

时间复杂度:只进行了一轮循环,故为O(n)

空间复杂度:O(1)

总结:这道题拿到手感觉有点类似leetcode第82.柱状图的最大矩形(大家感兴趣可以移步——柱状图的最大矩形),但是仔细看了会发现,其实不然,主要就是因为这道题没有考虑实际情况,忽略了中间的垂线,所以就简单很多,但还是值得一写的。

猜你喜欢

转载自blog.csdn.net/weixin_72076848/article/details/126049058