likes
comments
collection
share

盛水最多的容器:我待算法如初恋(五)

作者站长头像
站长
· 阅读数 16

前言

好吧,小菜鸡又来写算法啦! 刚刚写了一下力扣热题100道的第五道,就是之前我看了一眼说比较难的题(对我来说),因为他那个官方解题太复杂了。然后我在b站上学习了一下,然后再看这道题目好像确实不是好难得样子。好吧,咱们开始上题目了。

手刃算法第六式:盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。

说明: 你不能倾斜容器。

盛水最多的容器:我待算法如初恋(五)

拿到这道题目咱们先来分析一下题意:

题目分析

这道题目说的那么复杂,其实就是要咱们在一个数组里面找到两个数,使这两个数中较小的那个数与这两个数的下标差的乘积最大,并返回它俩的乘积。我当时看这个题目理解意思的时候以为是相邻的两条边,还是我把题目想的太复杂了。

理解了题意我们再来考虑,如何找这两个数呢?我们是不是首先想到的就是利用两个循环遍历,根据乘积的大小来确定这两个数。这就是我们常说的暴力枚举法,这种方法最简单,但是又是最烂的一种方法,因为它耗的时间是最多的,他的时间复杂度为O(n^2)。在这里还是给大家演示一下吧!

var maxArea = function(height) {
    let maxarea = 0;
    for(let i = 0; i < height.length; i++){
        for(let j = i + 1; j < height.length; j++){
            let area = Math.min(height[i],height[j])*(j-i)
            maxarea = Math.max(maxarea, area);
        }
    }
    return maxarea;
}

盛水最多的容器:我待算法如初恋(五)

这个方法是没有什么问题,只不过最后需要的时间太多了,导致超出了时间限制。

那除了这个方法还有什么方法呢?

我们其实还可以从从两头开始找。因为我们是要找到两条边中的最短的那条使他们的乘积最大,所以我们就应该是要移动最短的那条边。 否则的话,我们固定最短的那条边那个乘积就会越来越小。这个大家应该可以想到吧?就相当于求面积,已经固定了最短的那条边,再一直减小另外一条边,那么面积肯定是越来越小的,所以就不能固定最短的那条边了。

去实现它

设置两个指针分别指向数组的头部和尾部,再设置一个最大值,然后判断这两个数的大小,将最小的数乘以他们的下标差,判断最大值与它们的乘积的大小,取最大值。最后再移动值最小的指针直到两个指针重合前。

具体的代码实现:

/**
 * @param {number[]} height
 * @return {number}
 */
var maxArea = function(height) {
    let i=0;
    let j=height.length-1;
    let maxWater = 0;
    while(i<j){
        if(height[i]<height[j]){
            maxWater=Math.max(maxWater,height[i]*(j-i));
            i++;
        }
        else{
            maxWater = Math.max(maxWater,height[j]*(j-i));
            j--;
        }
    }
    return maxWater;
};

代码内容还是较为简单的。不过要注意一下,我们尾部指针应该是height.length-1,因为数组的下标是从0开始的。我就错了,别学我!

盛水最多的容器:我待算法如初恋(五)

还有没有简单的方法?

找了好久的最优解还没有找到,但是找到个超过了99%的人,不过那个代码就一行,看不懂实在看不懂!我现在还没到那种程度,就不拿过来献丑了,如果感兴趣的可以去Leecode的题解那里看看看。

总结

这道题我感觉还是挺有趣的,听说这道题是道典型的滑动窗口问题,所以滑动窗口问题是啥呢?有两个边界的,需要试探的,就是典型的滑动窗口问题。其实当我们思路捋顺了,拿下它还是很简单的。加油!兄弟们!

转载自:https://juejin.cn/post/7397628739885826083
评论
请登录