小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
盛最多的水
- 面积计算公式 : min(height[a],height[b])*(b-a)
方法一:暴力枚举
- 双层for,找出所有的可能的面积,选出最大值
- 缺点:时间复杂度高 n^2,leetcode运行不通过
/**
* 双层for循环,一个一个找,找出所有的组合的最大值,时间复杂度比较高
*
* @param height
* @return
*/
public static int maxArea(int[] height) {
int max = 0;
//注意:以下这种双层for能保证i和j不重复,且不会有反复的组合
for (int i = 0; i < height.length - 1; i++) {
for (int j = i + 1; j < height.length; j++) {
//计算面积,比较最大值
int area = (j - i) * Math.min(height[i], height[j]);
max = Math.max(area, max);
}
}
return max;
}
方法二:左右指针向中间收敛
- 创建左右指针,分别位于左右两侧。
- 每次将较矮的那个指针向中间移动,为什么呢,因为向中间移动后,(b-a)是变短了的,所以只有移动比较矮的那个指针,才有可能找到比较大的面积。
/**
* for循环,用两个指针从数组的两侧进行收敛,找出最大的面积
* <p>
* 找出数组中所有的组合的最大值
*
* @param height
* @return
*/
public static int maxArea2(int[] height) {
int max = 0;
int left = 0;
int right = height.length - 1;
while (left < right) {
//计算面积
int area = (right - left) * Math.min(height[right], height[left]);
//比较面积
max = Math.max(area, max);
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
return max;
}
/**
* 优化maxArea2中的代码,使其更加优雅
*
* @param height
* @return
*/
public static int maxArea3(int[] height) {
int max = 0;
int left = 0;
int right = height.length - 1;
while (left < right) {
//这里注意三元表达式中 left++ 和right-- 需要在 * 号的后面
int area = height[right] > height[left] ?
(right - left) * height[left++] : (right - left) * height[right--];
max = Math.max(area, max);
}
return max;
}