力扣的十一题——盛水最多的容器(双指针的运用)(附完整代码、思路讲解及知识点精炼)

题目介绍

给定一个长度为 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 <= 105
  • 0 <= height[i] <= 104

完整代码

public class Solution {
    public int maxArea(int[] height) {
        int l = 0, r = height.length - 1;
        int ans = 0;
        while (l < r) {
            int area = Math.min(height[l], height[r]) * (r - l);
            ans = Math.max(ans, area);
            if (height[l] <= height[r]) {
                ++l;
            }
            else {
                --r;
            }
        }
        return ans;
    }
}

 思路详解

1. 初始化双指针
  • l(left)指针初始化为数组的第一个元素,即最左边的线段。
  • r(right)指针初始化为数组的最后一个元素,即最右边的线段。
2. 循环计算面积
  • 使用一个while循环,当l小于r时,循环继续。这确保了我们在计算面积时,总是考虑两条不同的线段。
3. 计算当前面积
  • 在每次循环中,计算当前lr指向的两条线段所能围成的矩形面积。面积计算公式为:Math.min(height[l], height[r]) * (r - l)。这里使用Math.min函数是因为矩形的高度由较短的线段决定。
4. 更新最大面积
  • 使用变量ans存储当前已知的最大面积。在每次循环中,将当前计算出的面积与ans比较,并更新ans为两者中的较大值。
5. 移动指针
  • 根据当前lr指向的线段高度,决定移动哪个指针。如果height[l]小于或等于height[r],则将l指针向右移动(++l),因为我们希望通过移动较短的线段来寻找可能更大的面积。反之,如果height[l]大于height[r],则将r指针向左移动(--r)。
6. 返回结果
  • l不再小于r时,循环结束,此时ans变量中存储的就是最大面积。返回ans作为结果。

知识点精炼

1. 双指针技术
  • 利用两个指针分别从数组的两端开始,向中间移动,以减少不必要的遍历,提高算法效率。
2. 贪心算法
  • 在每一步选择中都采取当前状态下最优的选择,即移动较短的线段,以期找到可能的最大面积。
3. 面积计算
  • 使用矩形面积公式:面积 = 底 × 高,其中底是两个线段之间的距离,高是两个线段中较短的那个。
4. 动态更新最大值
  • 在遍历过程中,不断比较当前面积与已记录的最大面积,实时更新最大面积的值。
5. 循环条件
  • 使用while (l < r)作为循环条件,确保在计算面积时,始终处理两条不同的线段。
6. 空间复杂度优化
  • 仅使用常数额外空间(lrans),空间复杂度为O(1)。
7. 时间复杂度分析
  • 由于每个元素只被访问一次,算法的时间复杂度为O(n),其中n是数组的长度。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值