11.盛最多水的容器

97 篇文章 0 订阅
50 篇文章 0 订阅

11.盛最多水的容器

解题思路:

package leadcode;

/**
 * @author : icehill
 * @description : 盛最多水的容器
 * 给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。
 * 在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。
 * 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
 * <p>
 * 来源:力扣(LeetCode)
 * 链接:https://leetcode-cn.com/problems/container-with-most-water
 * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
 * 解题思路:
 * 1.暴力解法
 * 时间复杂度O(n^2)空间复杂度O(1)
 * 2.双指针(最优解)
 * 这个解法一开始也没想到,只是觉得有点规律,但是没证明
 * 分析过程:
 * 对于数组[a1,a2,……an],求最大的面积,上面的暴力解法就是对于
 * 每种可能进行枚举,然后计算面积,再求最大值,但是实际上有些情况可以不用计算
 * 前提:面积计算公式:min(a1,an)*(n-1)
 * (1).例如以a1为左边界,a2,a3……an为右边界,求这n-1个可能中的最大值
 * 如果a1<=an,那么无论a2,a3……an-1,比a1大还是小,根据面积计算公式,左半边min(a1,ak)<=min(a1,an),而(k-1)必定小于(n-1)
 * 所以如果a1<an,则只需要计算a1,an即可,
 * 如果a1>an,反过来,对于以an为右边界的所有可能,an*(n-1)最大,其他[a2,……an-1]为左边界的,到右边界an都不需要计算
 * 这样相当于每次我们无论移动左指针还是右指针,都能直接节省暴力解法一轮for循环
 * (2)接下来就是继续枚举a2为左边界,a3,a4……an,或者a1为做边界,a2,a3……an-1为有边界的所有可能,继续把这剩下的当做一个新的数组,重复(1)的过程
 * (3)根据上面的分析规律,我们可以定义双指针,每次移动较小的指针,比较一次,
 * 直到两个指针相遇中间所有可能的结果的最大值就是题解
 * 时间复杂度O(n)空间复杂度O(1)
 * @date : 2021-04-13
 */
public class Solution11 {
    public static void main(String[] args) {
        Solution11 solution11 = new Solution11();
        int[] arr1 = {1, 8, 6, 2, 5, 4, 8, 3, 7};
        int[] arr2 = {1, 1};
        int[] arr3 = {4, 3, 2, 1, 4};
        System.out.println(solution11.maxArea(arr1));
        System.out.println(solution11.maxArea(arr2));
        System.out.println(solution11.maxArea(arr3));
    }

    public int maxArea(int[] height) {
        //数组长度
        int lenght = height.length;
        if (lenght < 2) {
            return 0;
        }
        //双指针起始位置
        int begin = 0;
        int end = height.length - 1;
        //记录当前最大面积
        int maxArea = 0;
        while (begin < end) {
            //计算begin end直接的盛水面积(最小边界*两者之间长度)
            int currentArea = Math.min(height[begin], height[end]) * (end - begin);
            if (currentArea > maxArea) {
                maxArea = currentArea;
            }
            //移动较小值的指针,原因详见解题分析
            if (height[begin] <= height[end]) {
                begin++;
            } else {
                end--;
            }
        }
        return maxArea;
    }

    /**
     * 暴力解法
     *
     * @param height
     * @return
     */
    public int maxAreaTwo(int[] height) {
        //暴力做法
        int max = 0;
        int min = 0;
        for (int i = 0; i < height.length - 1; i++) {
            for (int j = i + 1; j < height.length; j++) {
                if (height[i] > height[j]) {
                    min = height[j];
                } else {
                    min = height[i];
                }
                if (((j - i) * min) > max) {
                    max = (j - i) * min;
                }
            }
        }
        return max;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值