【LeetCode】11-盛最多水的容器

297 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

11. 盛最多水的容器

题目描述

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

示例

question_11

示例一
输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例二
输入:height = [1,1]
输出:1

提示

  • n == height.length
  • 2 <= n <= 105
  • 0 <= height[i] <= 104

题解

本题很简单,就是通过输入的数组来计算最大的盛水容量,我们都知道,如果有两条垂线,那么能够盛水的高度肯定是以最短的那根线为准的,容量的计算方法就是两条垂线中最短的那条的高度 * 两条垂线之间的距离。

方法一

既然要计算最大值,那么最简单粗暴的方法就是直接使用循环,计算数组中每一个元素都和它后面的元素组成的容器大小,然后通过遍历找到最大值。

代码如下:

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

代码解析

通过Math.min计算两条垂线中较短的的高度乘以 j - i 得到的两条垂线之间的距离就能得到容器的容量大小。

时间复杂度:O(N^2)。

由于需要对数组进行双重循环,所以最后的时间复杂度较高,并且该方法也无法通过所有的测试用例,提交会报出超出时间限制的错误。

方法二

既然使用方法一的暴力方式无法解决问题,那么就需要找到另外一种方式,既然使用双重循环不行,那么还有一种方法就是使用两个指针,分别指向数组的最前面和最后面,然后不断的移动左指针和右指针完成对数组的遍历查找最大值,但是在指针移动的过程中不可能同时移动两个指针,所以就需要找到一个判断条件来判断到底是移动左指针还是右指针,这个条件就是通过比较两个指针指向的位置的元素的大小,哪个指针的元素更小则移动哪个指针,更大的那个元素的指针不动。

代码如下:

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

代码解析

时间复杂度:O(N)

通过该方法时间复杂度大大缩减,也可通过所有测试用例,假设盛水容量的公式为 w * h,使用双指针时,w 是不断递减的,在 w 递减的过程中通过改变 h 来找出最大的容量。