盛最多水的容器

题目

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0)(i, height[i])

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明: 你不能倾斜容器。

示例 1:

输入: [1,8,6,2,5,4,8,3,7]

输出: 49

解释: 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例 2:

输入: height = [1,1]

输出: 1

提示:

  • n == height.length
  • 2 <= n <= 10的5次方
  • 0 <= height[i] <= 10的4次方

分析

容器存储水量的计算公式为:

长 = j - i

高 = min(height[i],height[j])

存储水量 = (j - i) * min(height[i],height[j])

第一步:寻找题目的可行解法

我们可以计算每一种可能的结果,然后取最大值即可

两次循环即可,此时的时间复杂度为O(N^2)

第二步:优化这个解法,减少不必要的计算

依据计算公式,可以知道存储水量由长和高来决定

  • 长:j - i越大,结果越大
  • 高:min(height[i],height[j])越大,结果越大

为了尽可能的获取最大值,我们可以先使长最大,此时结果的大小由高来决定

此时有三种情况:

  1. height[i] > height[j],此时结果由短板height[j]来决定

长变小的两种情况:

  • i++,此时短板height[j]不变,所以min(height[i++],height[j]) <= height[j],由于长变小,高不变或变小,所以结果变小,没有变大的可能
  • j--,此时height[i]不变,height[j--]相对于height[j],可能会变大,变小或不变,长变小,所以结果可能会变大,变小或不变,有变大的可能
  1. height[i] < height[j],此时结果由短板height[i]来决定

长变小的两种情况:

  • i++,此时height[j]不变,height[i++]相对于height[i],可能会变大,变小或不变,长变小,所以结果可能会变大,变小或不变,有变大的可能
  • j--,此时短板height[i]不变,所以min(height[i],height[j--]) <= height[i],由于长变小,高不变或变小,所以结果减小,没有变大的可能
  1. height[i] = height[j],此时结果由height[i]和height[j]决定

长变小的两种情况:

  • i++,min(height[i++],height[j]) <= height[j],长变小,高不变或变小,所以结果变小,没有变大的可能
  • j--,min(height[i],height[j--]) <= height[i],长变小,高不变或变小,所以结果变小,没有变大的可能

整理思路:

  1. 找到最大的长,定义两个指针i = 0,j = len(height) - 1,记录当前结果
  2. 比较高的大小,当height[i] > height[j]时,移动短板的height[j]才可能使结果变大,j--,移动后记录结果最大值
  3. 当height[i] < height[j]时,移动短板的height[i]才可能使结果变大,i++,移动后记录结果最大值
  4. 当height[i] = height[j]时,移动i或j,结果都是变小,任意移动一个即可
  5. 当i >= j时,结束判断

代码

使用什么语言都无所谓,重点是理解思想

golang代码如下:

go 复制代码
func maxArea(height []int) int {
    var result int
    // 特殊判断
    if len(height) <= 1 {
        return result
    }

    // 定义两个指针
    i := 0
    j := len(height) - 1
    for i < j {
        // 长
        w := j - i
        // 高,默认值选择height[i]
        h := height[i]
        if height[i] > height[j] {
            // 当短板是height[j]时,使高等于短板
            h = height[j]
            // 移动短板对应的下标
            j--
        } else {
            // 短板是height[i]或height[i] = height[j],移动短板对应的下标
            i++
        }

        // 计算当前结果
        temp := h * w
        // 判断和保存结果最大值
        if temp > result {
            result = temp
        }
    }
    return result
}
  • 时间复杂度:O(N),双指针遍历数组
  • 空间复杂度:O(1),常量空间
相关推荐
YuTaoShao3 分钟前
【LeetCode 每日一题】1653. 使字符串平衡的最少删除次数——(解法一)前后缀分解
算法·leetcode·职场和发展
VT.馒头9 分钟前
【力扣】2727. 判断对象是否为空
javascript·数据结构·算法·leetcode·职场和发展
goodluckyaa18 分钟前
LCR 006. 两数之和 II - 输入有序数组
算法
孤狼warrior19 分钟前
YOLO目标检测 一千字解析yolo最初的摸样 模型下载,数据集构建及模型训练代码
人工智能·python·深度学习·算法·yolo·目标检测·目标跟踪
Σίσυφος190043 分钟前
PCL法向量估计 之 RANSAC 平面估计法向量
算法·机器学习·平面
xhbaitxl1 小时前
算法学习day39-动态规划
学习·算法·动态规划
I_LPL1 小时前
day23 代码随想录算法训练营 回溯专题2
算法·hot100·回溯算法·求职面试
智者知已应修善业1 小时前
【洛谷P9975奶牛被病毒传染最少数量推导,导出多样例】2025-2-26
c语言·c++·经验分享·笔记·算法·推荐算法
m0_736919101 小时前
C++中的委托构造函数
开发语言·c++·算法
小小小小王王王1 小时前
洛谷-P1886 【模板】单调队列 / 滑动窗口
c++·算法