题目详情如下图所示:
解题思路
拿到这道题的 第一个想法就是,双层循环遍历法,找出所有可能的组合,求出面积,然后比较,最终求出最大的面积。下面是具体的代码
class Solution{
public int maxArea(int[] height){
int max = 0;
int area = 0;
//第一层循环需要限制height.length-1
for(int i = 0; i < height.length - 1; ++i){
//第二层循环y需要每次从i+1开始
for(int y = i + 1; y < height.length; ++y){
//求出面积,并比较得出最大值保存。共最后返回用
area = (y - i) * Math.min(heigth[i] , heigth[j]);
max = Math.max(max, area);
}
}
return max;
}
}
当然写完这个方法我们方法这个方法有点挫,他的时间复杂度有点高。是O(n^2)的。
这里面需要注意的一个点是书写双层循环遍历数组的写法问题,对于i和j的取值问题需要注意,因此特地拿出来说。
有没有更加简便的方法呢?
当然有
我们应该想到:面积等于 长 * 高
当长和高都是最高或者说长和高都是我们这里的最优解的时候,面积不就是最大了吗
所以我们设置两个变量,首先从数组的首尾两端来进行查找。
在首尾两端时,长度是最大的。那么这个时候就需要向中间移动去寻找不同的情况
我们如何进行移动呢?
我们看图可知。求面积时,我们能选取的高度是两个柱子中最小的那个柱子作为围成长方形的高。如图所示
抓住了这一点,我们就能知道:
每次移动两个柱子中相对较小的那个柱子,小的那个柱子变大了 就会使得总面积变大(因为如果移动较高的哪一个柱子的话,要么比较小的大,那么我们能选取的还是较小的高度,要么就是比较小的还小,这样就会使得面积变小,因此我们只能移动最小的柱子才能获取最大面积)。这就是解这道题的关键。
所以这道题的解题思路就是,从两边向中间收敛,每次移动相对较小的那个柱子,使得围成图形的高度尽可能变大。当收敛到一起即两个变量相遇时就结束了。(两个变量会相遇,但是不一定是在中间)
具体的代码就是如下所示:
class Solution {
public int maxArea(int[] height) {
int max = 0;
int minHeight = 0;
int area = 0;
for(int i = 0, j = height.length-1; i != j;){
//因为我们在确定柱子的移动的时候,需要做一次柱子大小的判断,同时在求面积的时候也要做一次大小的判断
//所以我们没有必要做两次判断,可以综合一下只做一个判断。就是我们的双目运算符,这是点睛之笔!!!!
minHeight = height[i] < height[j] ? height[i++] : height[j--];
//因为提前做了移动,这里求面积的时候应该加1
area = (j - i + 1) * minHeight;
max = Math.max(max,area);
}
return max;
}
}
全文完!