leetcode(11.盛最多水的容器)【中等】

一、题目

给定一个长度为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

二、题解

方法一:双层for循环【超出时间限制】
双层for循环,每次计算外层循环当前位置值与内层所有元素组成的容器容量curWater,设置maxWater判断其与curWater的大小关系,更新maxWater
方法二:双指针

[1, 8, 6, 2, 5, 4, 8, 3, 7]
 ^                       ^ 

在初始时,左右指针分别指向数组的左右两端,它们可以容纳的水量为 min⁡(1,7)∗8=8。

此时需要移动一个指针,应该移动对应数字较小的那个指针(即此时的左指针)。由于容纳的水量是由

两个指针指向的数字中较小值∗指针之间的距离

决定。
如果移动数字较大的那个指针,那么前者「两个指针指向的数字中较小值」不会增加,后者「指针之间的距离」会减小,那么这个乘积会减小。因此,移动数字较大的那个指针是不合理的。于是,移动 数字较小的那个指针
所以,将左指针向右移动:

[1, 8, 6, 2, 5, 4, 8, 3, 7]
    ^                    ^ 

此时可以容纳的水量为 min⁡(8,7)∗7=49。由于右指针对应的数字较小,移动右指针:

[1, 8, 6, 2, 5, 4, 8, 3, 7]
    ^                 ^ 

此时可以容纳的水量为 min⁡(8,3)∗6=18。由于右指针对应的数字较小,移动右指针:

[1, 8, 6, 2, 5, 4, 8, 3, 7]
    ^              ^ 

此时可以容纳的水量为 min⁡(8,8)∗5=40。两指针对应的数字相同,可以任意移动一个,例如左指针:

[1, 8, 6, 2, 5, 4, 8, 3, 7]
       ^           ^ 

此时可以容纳的水量为 min⁡(6,8)∗4=24。由于左指针对应的数字较小,移动左指针,并且可以发现,在这之后左指针对应的数字总是较小,因此之后会一直移动左指针,直到两个指针重合。在这期间,对应的可以容纳的水量为:min⁡(2,8)∗3=6,min⁡(5,8)∗2=10,min⁡(4,8)∗1=4。
在移动指针的过程中,计算到的最多可以容纳的数量为 49,即为最终的答案。

三、代码

方法一:双层for循环【超出时间限制】

import java.util.Scanner;

public class MaxArea_11 {
    public static int maxArea(int[] height) {
        int maxWater = 0;
        for (int i = 0; i < height.length; i++) {
            for (int j = 0; j < height.length; j++) {
                int h = Math.min(height[i],height[j]);
                int w = Math.abs(i - j);
                int curWater = w * h;
                if(curWater > maxWater){
                    maxWater = curWater;
                }
            }
        }
        return maxWater;
    }
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String[] s = sc.nextLine().split(",");
        int num[] = new int[s.length];
        for(int i = 0; i < s.length; i++){
            num[i] = Integer.valueOf(s[i]);
        }
        System.out.println("最大盛水量:" + maxArea(num));
    }
}

方法二:双指针

import java.util.Scanner;

public class MaxArea_11_2 {
    public static int maxArea(int[] height) {
        int l = 0, r = height.length - 1;
        int maxWater = 0, curWater = 0;
        while (l < r) {
            curWater = Math.min(height[l], height[r]) * (r - l);
            maxWater = Math.max(maxWater, curWater);
            if (height[l] < height[r]) {
                l++;
            } else {
                r--;
            }
        }
        return maxWater;
    }
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String[] num = sc.nextLine().split(",");
        int[] n = new int[num.length];
        for(int i = 0; i < num.length; i++){
            n[i] = Integer.valueOf(num[i]);
        }
        System.out.println("最大容水量:" + maxArea(n));
    }
}

四、结果

方法一:【超出时间限制】
在这里插入图片描述

方法二:双指针
在这里插入图片描述

五、说明

  本文章仅用于记录个人做题记录
  由于本人是个小菜鸡(实锤),题目解法并非最优,且解题过程中参考(抄袭)各大佬解题方法,望见谅。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值