【LeetCode笔记】11. 盛最多水的容器(中等)

133 阅读1分钟

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器。

image.png

分析: 这题一开始想用暴力直接算出来,也就是时间复杂度O(N^2)的方法,结果最后一场超长数组的测试用例直接没通过,超时了QAQ。但我觉得在实际面试的时候,如果一时想不到太好的办法,直接暴力也不是一个坏的办法。下面附个暴力解法:

func maxArea(height []int) int {
    var maxArea int = 0
    var tempArea int = 0
    if len(height) <= 1 {
        return 0
    }
    for i := 1; i <= len(height); i++ {
        for j := i+1; j <= len(height); j++ {
            if height[j-1] < height[i-1] {
                tempArea = height[j-1]*(j-i)
            } else {
                tempArea = height[i-1]*(j-i)
            }
            if tempArea > maxArea {
                maxArea = tempArea
            }
        }
    }
    return maxArea
}

当然啦,正经人谁用暴力解法嘛!这题应该还是用双指针的解法。一个指向数组第一个数,一个指向数组最后一个数,求出面积后,再移动比较小的一端,之所以要移动高度小的一端指针,是因为这个面积是由两边高度矮的一方决定的(木桶效应嘿嘿嘿?)所以,如果移动高的一端指针,并不会使得面积变大,而且由于宽的减少,面积只会减少,因此我们不断移动矮的一端的指针,直至指针相遇。附代码:

func maxArea(height []int) int {
    i, j := 0, len(height) - 1
    m := 0
    for i < j {
        // 计算当前最大面积
        cur := (j - i) * min(height[i], height[j])
        if cur > m {
            m = cur
        }

        // 移动较小的一侧指针
        if (height[i] < height[j]) {
            i++
        } else {
            j--
        }
    }
    return m
}

func min(x, y int) int {
    if x > y {
        return y
    }
    return x
}