给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (iai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (iai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2

 

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

Example:

Input: [1,8,6,2,5,4,8,3,7]
Output: 49

说实话,没这图我还真没看明白这题啥意思,然而英文站点的图居然挂了= =
抱着尝试的心态输入了-ch,果然路由是镜像的。

至于题目嘛。。不管不管Brute Force:

 1 public class Solution {
 2     public int MaxArea(int[] height) {
 3         int result = 0;
 4         for (int i = 0; i < height.Length - 1; i ++)
 5         {
 6             for (int j = i + 1; j < height.Length; j ++)
 7             {
 8                 result = Math.Max(Math.Min(height[i], height[j]) * (j - i), result);
 9             }
10         }
11         return result;
12     }
13 }

O(n2)的复杂度竟然让运行时间达到了1000+。。

优化

可以说大部分算法优化的思路就是省去不必要的计算,那这道题有哪些不必要的计算呢?

因为题目规定水的高度是由较短的一条线决定的,那么对于数组中的最小值,能和他组成最大面积的那条线即是距离他最远的值。

那么依次类推,我们需要考虑比较的,仅仅是“每条线和比自身长的且距离最远的线组成的面积”。

[1,8,6,2,5,4,8,3,7]为例:

考虑的情况有:

f(1,7) = 1*8

f(8,8) = 8*5

f(6,7) = 6*7

f(2,7) = 2*5

f(5,7) = 5*4

f(4,7) = 4*3

f(8,8) = 8*5

f(3,8) = 3*6

f(7,8) = 7*7

那么显然,这道题只需要O(n)的复杂度就可以解决了。

但是这种思路在实际编程时不太好实现,毕竟需要依次比较大小。

双指针

兜了半天圈子其实这道题也算是个标准的双指针题,从两边开始,不断向中间移动较小的那一边的值。

这里还有个可以优化的点,就是如果移动后指针所在的值没有大于之前所在的值,那也不必计算了。

 1 public class Solution {
 2     public int MaxArea(int[] height) {
 3         int l = 0;
 4         int r = height.Length - 1;
 5         int temp = Math.Min(height[l], height[r]);
 6         int result = temp * (r - l);
 7         while (l < r)
 8         {
 9             if (height[l] < height[r])
10             {
11                 l ++;
12                 if (height[l] <= temp)
13                 {
14                     continue;
15                 }
16             }
17             else
18             {
19                 r --;
20                 if (height[r] <= temp)
21                 {
22                     continue;
23                 }
24             }
25             temp = Math.Min(height[l], height[r]);
26             result = Math.Max(temp * (r - l), result);
27         }
28         return result;
29     }
30 }

提交后竟然只超过52%,挺吃惊的:

 

吓的我赶紧用其他语言实现了一下

java:99.98%

python:94.4%

 

 cpp:98.47%

???(黑人问号脸)

不知道是不是服务端的CLR环境有点问题,总感觉碰到数组的题c#就特别慢。不管了,还是计算时间复杂度说话吧