11. Container With Most Water

本文探讨了LeetCode上的经典问题——寻找能盛最多水的容器。通过直观的图形解释和逐步深入的算法分析,从暴力求解到优化后的双指针策略,详细介绍了如何高效解决这一挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题

Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). 
n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). 
Find two lines, which together with x-axis forms a container, such that the container contains the most water.

Note: You may not slant the container and n is at least 2.

翻译

给定n个非负整数a 1, 2,…其中每个表示坐标点(i, ai)。
直线的两个端点是(i, ai)和(i, 0)。
找到两条直线,与x轴一起形成一个容器,这样容器就包含了最多的水。

嗯,先让我们来看一下题目。What a fucking thing is this?


莫慌,我们先上张图,帮助理解(PS画风直击灵魂)


大概意思就是,Y轴上的两个点,连成的线,与另外一根线加上X轴组合成一个容器,这些线能够组合成的容器中,装水最多的是哪一组,如图则为画阴影的部分,嗯如果这也算阴影的话,也就是点(1,a1)和(4,a4)组合成的容器。

例如int[] height = {3,5,7,9,10,2,1,12} 中能组合成最大容器的点为(4,9)和(8,12),返回的值则为(8-4)*(Math.min(9,12))=36

public int maxArea(int[] height) {
        int result = 0;
        for (int i = 0; i < height.length; i++) {
            for (int j = height.length - 1; j >= 0; j--) {
                int temp = (j - i) * Math.min(height[i], height[j]);
                result = Math.max(result, temp);
            }
        }
        return result;
    }

是不是很简单?抱歉,如果真这么简单,LeetCode也不至于分级属于中等难度了,拿去一提交,发现

Submission Result: Time Limit Exceeded

提交超时,看样子虽然题目中没有给出时间复杂度的要求,但是最终校验的时候还是会有这样的,既然这样,这套思路就不太能走得通了,因为双层循环优化下去,也无法有显著的性能提升。

既然这样,我们再回到上面那个例子int[] height = {3,5,7,9,10,2,1,12} ,如果让我们人工来找出最大的一组数据怎么会怎么找呢?

是不是先从左往右找到一个较大的数字,比如7,然后再从右往左找出一个较大的数,12,然后计算,再算下9和10就差不多了。既然这样,我们程序其实也可以这样写。

不过程序无法估计出一个合适的位置找到较大的数进行,那么我们就从最左边和最右边,找到一个数,但是这次不是两边都动了,我们前面计算的时候都知道,7算完12不动,因为12比7要大,如果12都不行的话,那么7就更不行了,毕竟都是移动一位。

至于原理,根据题目的特殊性,X每次移动都是"1",而Y的变化最少是"1",那么我们只需要确保每次计算的高都比上一次的要高,那么容器就可以确保是最大的。我们每次计算都是记录的两个最大高度的值,这样得到的结果也就是最大的,


文字说起来比较空洞,直接上代码吧

public int maxArea(int[] height) {
        int i =0, j = height.length - 1;
        int result = 0;
        while (i != j){
            int temp = (j - i) * Math.min(height[i], height[j]);
            result = Math.max(result, temp);
            if (height[i] > height[j])
                j--;
            else
                i++;
        }
        return result;
    }


点击查看更多解法



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值