第一种:枚举(略微优化,不超时)
public int maxArea(int[] height) {
int max = 0; // 最大水量
// 从左往右遍历左半部分
for (int i = 0; i <= (height.length - 1) / 2; i++) {
for (int j = height.length - 1; j > i; j--) {
if (height[i] <= height[j]) {
max = Math.max(max, (j - i) * height[i]); // 计算当前容器的水量并更新最大水量
break; // 因为移动右指针 j 时,容器的宽度只会减小,而高度不变或增加,因此不需要再继续循环
}
}
}
// 从右往左遍历右半部分
for (int i = (height.length - 1) / 2 + 1; i < height.length; i++) {
for (int j = 0; j < i; j++) {
if (height[i] <= height[j]) {
max = Math.max(max, (i - j) * height[i]); // 计算当前容器的水量并更新最大水量
break; // 因为移动左指针 j 时,容器的宽度只会减小,而高度不变或增加,因此不需要再继续循环
}
}
}
return max; // 返回最大水量
}
第二种:双指针
public int maxArea(int[] height) {
int left = 0; // 左指针
int right = height.length - 1; // 右指针
int max = 0; // 最大水量
while (left < right) {
// 计算当前容器的水量并更新最大水量
max = Math.max(max, (right - left) * Math.min(height[left], height[right]));
// 移动指针的策略:
// 如果左边界的高度小于右边界的高度,那么向右移动左指针,寻找可能更大的水量
// 如果右边界的高度小于等于左边界的高度,那么向左移动右指针,寻找可能更大的水量
if (height[left] > height[right]) {
right--;
} else {
left++;
}
}
return max; // 返回最大水量
}
第一种思路是,先从左往右遍历数组,找到每个位置作为容器左边界时的最大水量;然后从右往左遍历数组,找到每个位置作为容器右边界时的最大水量;最终返回两次遍历得到的最大水量中的较大值作为结果。
然而,这个解法的时间复杂度较高,为 O(n^2),其中 n 是数组的长度。因为使用了两层嵌套循环,每次遍历都需要进行大量的比较和计算,导致时间复杂度较高。
相比之下,使用双指针法的解法在时间复杂度上更优,仅为 O(n)。