一、题目
给定一个长度为n的整数数组height。有n条垂线,第i条线的两个端点是(i, 0)和(i,height[i])。
找出其中的两条线,使得它们与x轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入:height = [1,1]
输出:1
提示:
- n == height.length
- 2 <= n <= 105
- 0 <= height[i] <= 104
二、题解
方法一:双层for循环【超出时间限制】
双层for循环,每次计算外层循环当前位置值与内层所有元素组成的容器容量curWater,设置maxWater判断其与curWater的大小关系,更新maxWater
方法二:双指针
[1, 8, 6, 2, 5, 4, 8, 3, 7]
^ ^
在初始时,左右指针分别指向数组的左右两端,它们可以容纳的水量为 min(1,7)∗8=8。
此时需要移动一个指针,应该移动对应数字较小的那个指针(即此时的左指针)。由于容纳的水量是由
两个指针指向的数字中较小值∗指针之间的距离
决定。
如果移动数字较大的那个指针,那么前者「两个指针指向的数字中较小值」不会增加,后者「指针之间的距离」会减小,那么这个乘积会减小。因此,移动数字较大的那个指针是不合理的。于是,移动 数字较小的那个指针。
所以,将左指针向右移动:
[1, 8, 6, 2, 5, 4, 8, 3, 7]
^ ^
此时可以容纳的水量为 min(8,7)∗7=49。由于右指针对应的数字较小,移动右指针:
[1, 8, 6, 2, 5, 4, 8, 3, 7]
^ ^
此时可以容纳的水量为 min(8,3)∗6=18。由于右指针对应的数字较小,移动右指针:
[1, 8, 6, 2, 5, 4, 8, 3, 7]
^ ^
此时可以容纳的水量为 min(8,8)∗5=40。两指针对应的数字相同,可以任意移动一个,例如左指针:
[1, 8, 6, 2, 5, 4, 8, 3, 7]
^ ^
此时可以容纳的水量为 min(6,8)∗4=24。由于左指针对应的数字较小,移动左指针,并且可以发现,在这之后左指针对应的数字总是较小,因此之后会一直移动左指针,直到两个指针重合。在这期间,对应的可以容纳的水量为:min(2,8)∗3=6,min(5,8)∗2=10,min(4,8)∗1=4。
在移动指针的过程中,计算到的最多可以容纳的数量为 49,即为最终的答案。
三、代码
方法一:双层for循环【超出时间限制】
import java.util.Scanner;
public class MaxArea_11 {
public static int maxArea(int[] height) {
int maxWater = 0;
for (int i = 0; i < height.length; i++) {
for (int j = 0; j < height.length; j++) {
int h = Math.min(height[i],height[j]);
int w = Math.abs(i - j);
int curWater = w * h;
if(curWater > maxWater){
maxWater = curWater;
}
}
}
return maxWater;
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] s = sc.nextLine().split(",");
int num[] = new int[s.length];
for(int i = 0; i < s.length; i++){
num[i] = Integer.valueOf(s[i]);
}
System.out.println("最大盛水量:" + maxArea(num));
}
}
方法二:双指针
import java.util.Scanner;
public class MaxArea_11_2 {
public static int maxArea(int[] height) {
int l = 0, r = height.length - 1;
int maxWater = 0, curWater = 0;
while (l < r) {
curWater = Math.min(height[l], height[r]) * (r - l);
maxWater = Math.max(maxWater, curWater);
if (height[l] < height[r]) {
l++;
} else {
r--;
}
}
return maxWater;
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String[] num = sc.nextLine().split(",");
int[] n = new int[num.length];
for(int i = 0; i < num.length; i++){
n[i] = Integer.valueOf(num[i]);
}
System.out.println("最大容水量:" + maxArea(n));
}
}
四、结果
方法一:【超出时间限制】
方法二:双指针
五、说明
本文章仅用于记录个人做题记录
由于本人是个小菜鸡(实锤),题目解法并非最优,且解题过程中参考(抄袭)各大佬解题方法,望见谅。