题目:给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
class Solution {
public int maxArea(int[] height) {
/*思路(暴力):height保存线高,两线之间的角标差值就是底,有效存水面积就是低与两线之间较小值的乘积。
可以依次计算每两线之间的存水量,留下最大的结果。*/
int temp;
int result = 0;
for (int i = 0; i < height.length; i++) {
for (int j = i + 1; j < height.length; j++) {
temp = Math.min(height[i],height[j]) * (j - i);
if (result < temp) {
result = temp;
}
}
}
return result;
}
}
代码运行没问题,一提交,果然超出了时间限制。我还是太菜了。
=========================================================================
这个题的难度在于,不仅仅需要找到尽可能的边长,而且在找尽可能的边长的同时寻找尽可能的低长(脚标差),因此常规的排序达不到效果。到这里我的脑子就想不出什么好办法了,看看大佬们怎么解决的吧!
查了一下官方思想:
在每个状态下,无论长板或短板向中间收窄一格,都会导致水槽 底边宽度 -1 变短:
若向内移动短板 ,水槽的短板 min(h[i],h[j]) 可能变大,因此下个水槽的面积可能增大 。
若向内 移动长板 ,水槽的短板 min(h[i],h[j]) 不变或变小,因此下个水槽的面积一定变小 。
因此,初始化双指针分列水槽左右两端,循环每轮将短板向内移动一格,并更新面积最大值,直到两指针相遇时跳出;即可获得最大面积。
按照这个思想编写一手:
class Solution {
public int maxArea(int[] height) {
//初始化双指针
int i = 0;
int j = height.length - 1;
//记录最大结果
int temp;
int result = 0;
while (i < j) {
temp = (j - i) * Math.min(height[i], height[j]);
if (result < temp) {
result = temp;
}
//移动水槽板过程
if (height[i] > height[j]) {
j--;
} else {
i++;
}
}
return result;
}
}
=========================================================================
在讨论区看到了有个大佬在官方解答基础上,引入了快速跳过过程,大大提交了效率,惊为天人!
class Solution {
public int maxArea(int[] height) {
//初始化双指针
int i = 0;
int j = height.length - 1;
//结果
int temp;
int result = 0;
while (i < j) {
temp = (j - i) * Math.min(height[i], height[j]);
int minHeight = Math.min(height[i], height[j]);
result = Math.max(result, temp);
//相比于之前一次只推一格木板,一次推多格木板
while (height[i] <= minHeight && i < j) {
i++;
}
while (height[j] <= minHeight && i < j) {
j--;
}
}
return result;
}
}