LeetCode P11--盛最多水的容器

题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/container-with-most-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

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

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

示例:

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

可能很多人刚看到这道题第一想法就是暴力法—就是每两个垂直线都算一遍容水量,然后选最大值。这个我也想到了:

class Solution {
    List<List<Integer>> output = new LinkedList();
    int n;
    int k;
    //回溯
    public void backtrack(int first, LinkedList<Integer> curr) {
        // 如果组合中的个数达到要组合的数量,则加入到列表中
        if (curr.size() == k)
                output.add(new LinkedList(curr));
		//遍历把每个数都加入列表,最后又移除
        for (int i = first; i < n + 1; ++i) {
            // add i into the current combination
            curr.add(i);
            // use next integers to complete the combination
            backtrack(i + 1, curr);
            // backtrack
            curr.removeLast();
        }
    }
	//从n个数里获取k个数的组合
    public List<List<Integer>> combine(int n, int k) {
        this.n = n;
        this.k = k;
        backtrack(1, new LinkedList<Integer>());
        return output;
    }
	//依次计算每个组合中的容纳水的量,并取最大值
    public int maxArea(int[] height) {
        List<List<Integer>> rs = combine(height.length,2);
        int max = 0;
        for (int i=0;i<rs.size();i++){
            List<Integer> temp = rs.get(i);
            int a = temp.get(0);
            int b = temp.get(1);
            max = Math.max(max,(b-a)*Math.min(height[a-1],height[b-1]));
        }
        return max;
    }
}

很遗憾的是,,这个方法超时了,或许可以继续优化这种方法,但是我没有再去优化。因为想起了之前的”双指针法”

我们可以一个指针指向最左边,一个指向最右边,计算一次容水量,并和原来的容水量作比较(最开始可以初始化为0),然后选择较大的一个。
接下来关键的一步就是移动指针,那么到底是==**移动左指针还是右指针呢?**我们可以想一想,如果左指针当前指的垂直线高度较高,那么它的容纳性就更高,换句话说,我们就是要移动垂直线高度较小的一边,以便能尽量获取更大的容水量。
下面是实现代码:

//双指针法
    public int maxArea(int[] height) {
		//初始化最大容水量为0
        int max = 0;
        //l为左指针,r为右指针,初始先放在左右两端
        int l=0,r = height.length-1;
        while (l<r){
        //取较大的容水量,并更新
            max = Math.max(max,(r-l)*Math.min(height[l],height[r]));
            //如果左边的垂直线高度比右边的低,就把左指针往右移动,
            //否则就把右指针向左移动
            if (height[l]<=height[r]){
                l+=1;
            }else {
                r-=1;
            }
        }
        return max;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值