Algorithm之路十一:Container With Most Water

来源:互联网 发布:程序员一句话工作总结 编辑:程序博客网 时间:2024/05/24 01:51

题目:

给出一个整形数组,其中的元素为a1,a2,……an,现在在平面直角坐标系中作出点(i,ai),并与(i,0)连线,共形成n条线,现在任选两条线,可以个x轴形成一个容器,如果在这个容器中加水,如何选择n条线中的两条,才可以使得这两条线和x轴围成的容器装的水的面积更大。

Note:n大于1

举例:

1 8 6 2 5 4 8 3 7
最大面积为(a9*(9-2)) = 49,

思路:

将题目理解之后,就明白了,题目实际上是要求找i,j,使得|min(ai - aj)*(i - j)|最大,最容易想到的就是暴力搜索,将所有情况的i,j组合都找到,但是显然这种方法简单易懂,肯定不是一个比较优秀的方法。

以下是一个时间复杂度为O(n)的策略:

具体的计算过程请看https://leetcode.com/problems/container-with-most-water/solution

我们知道一个容器能装多少水是由最短的板决定的,在题目中的这个二维的容器中,能装多少水,则看的较短的那个边,同时也要考虑底部的长度。

对于某个i,j,计算|(ai - aj)*(i - j)|,和maxarea比较,并更新maxarea的值,如果ai < aj,则i++,否则j--。

在比较aiaj的大小这一步,实际上相比于暴力搜索法省略掉了多步,在计算|(ai - aj)*(i - j)|时,假如ai < aj那么此时计算ai和aj-1,ai和aj-1,……ai和ai+1对应的直线之间的面积已经没有意义。原因如下:对于i + 1 <= m <= j - 1,若am > ai,此时容器的高度为ai,|(ai - am)*(i - m)|的值显然小于|(ai - aj)*(i - j)|的值,若am < ai,此时容器的高度为am,而m <= j - 1,|(ai - am)*(i - m)|的值仍然小于|(ai - aj)*(i - j)|的值,所以此时计算|(ai - am)*(i - m)|的值已经没有意义。所以这个时间复杂度为O(n)的策略比暴力搜索法省去了好多步骤,并且求得结果是正确的。

代码:

public class Container_With_Most_Water {public static int maxArea(int[] height){int n = height.length;int start = 0;int end = n - 1;int maxarea = 0;while(end >= start){maxarea = Math.max(maxarea, Math.abs((start - end)*(Math.min(height[start],height[end]))));if(height[start] > height[end])end--;elsestart++;}return maxarea;    }public static void main(String[] args){int[] height = {1,8,6,2,5,4,8,3,7};System.out.println(maxArea(height));}

时间复杂度:

只把数组遍历了一次,时间复杂度为O(n)。

空间复杂度:

O(1)。

原创粉丝点击