LeetCode上的11号题,类型为中等
题目:
给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例:
输入: [1,8,6,2,5,4,8,3,7]
输出: 49
本人算法不太好,所以最近一直在刷题,想着分享一点不说是经验,就一些刷题感想吧。
如果想一起研究一起学习的可以加入我的算法群 :756788889
首先这题先弄清楚怎么算面积,如题意所示 两个下标之间的面积,既然是要容纳水 自然是用最低(最小的)的坐标来计算的
容纳的宽度自然是坐标差啦,所以得到一个简单的公式:
最大面积 = 最小下标 * 下标差
其实这里考验是遍历而不是这个计算 ,所以真正是要求怎么快速遍历 接下来用代码实现
暴力法
像我这种小白一般一开始就暴力法搞起,不考虑时间复杂度的,不过既然是算法题,还是不太建议使用暴力法,毕竟太low
上代码,其实没啥好说的只要两层遍历 然后加上算面积的公司 就好了 。这里复杂度 O(n2)
如果你使用的是Java 这里可以使用 Java的方法 来比较大小。不过感觉差不多 我一般不太使用Java的方法来写。毕竟算法是大家的,哈哈
max= Math.max(maxarea, Math.min(height[i], height[j]) * (j - i));
public static int maxArea2(int[] height) {
/**
* 几种情况
* 1、两个数最小值 中间个数查
* 2、其实可以得出 以下公式:
* 最小数 * 个数 坐标差 * 最小值
*/
int max = 0;
int area = 0;
for (int i = 0; i <height.length ; i++) {
for (int j = i+1; j < height.length; j++) {
//先判断大小
if(height[i]>height[j]){
area = height[j] * (j-i);
}else {
area = height[i] * (j-i);
}
if(area>max){
max = area;
}
}
}
return max;
}
看下时间这个确实不太好
接下来就是常用套路方法了
双指针法
就是两端慢慢的逼近,不懂的可以去查查资料,很多这类题(数组)都可以使用这个方法。
public static int maxArea3(int[] height) {
int left = 0, right = height.length - 1;
int max = 0,area = 0;
while (left < right) {
if (height[left] > height[right]) {//这里一般是最大值
area = height[right] * (right - left);
right--;
} else {
area = height[left] * (right - left);
left++;
}
if (area > max) {
max = area;
}
}
return max;
}
这个显然就好多了,而且时间复杂度 O(n)O(n),一次扫描。
还有一些其他解法:
项目地址: github