leetcode - 盛水最多的容器 11

2019/10/10 leetcode

leetcode - 盛水最多的容器 - 11

Question 1

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

说明:你不能倾斜容器,且 n 的值至少为 2。

思路

  • 盛水的多少,取决于底和高。

    高只取决于最低的那条边,所以取 min(height[head], height[tail])

    底就是当前两条高之间的距离, tail - head

    所以面积为 : (tail-head) * min(height[head], height[tail])

  • 何时更新 head 和 tail 呢?

    当 height[head] < height[tail] 时,继续更新 tail = tail-1 则 损失了可能作为 高 的 height[tail], 而且 底 是在减小的, 所以只会获取更小的值。

    1, 当前值 height[head] * (tail-head) 2, 更新值 height[head+1] * (tail-head)

  • 整体逻辑

    while head < tail:
        area = max(area, (tail-head)*min(height[head], height[tail]))
        if height[head]<height[tail]:
            head += 1
        else :
            tail -= 1

暴力法

遍历每组可能出现的组合,寻找最大值。

分析

时间复杂度为 O(n*(n-1))
func maxArea(height []int) int {
    maxArea := 0
    length := len(height)
    for i:=0; i<length; i++ {
        for j:=i+1; j<length; j++ {
            tempHeight := height[j]
            if height[i]<height[j]{
                tempHeight = height[i]
            }
            tempArea := (j-i) * tempHeight
            if tempArea > maxArea {
                maxArea = tempArea
            }
        }
    }
    return maxArea
}

双指针法

头指针与尾指针向中间遍历。

分析

前后双指针
func maxArea(height []int) int {
    maxArea := 0
    length := len(height)
    head := 0
    tail := length - 1
    for ;; {
        if head >= tail{
            break
        }
        tempHeight := height[tail]
        if height[head] < height[tail]{
            tempHeight = height[head]
        } 
        areaTemp := tempHeight * (tail-head)
        if areaTemp > maxArea{
            maxArea = areaTemp
        }
        
        if height[head] > height[tail]{
            tail = tail - 1
        } else {
            head = head + 1
        }
    }
    return maxArea
}
Show Disqus Comments

Search

    Post Directory